File: Token.xs

package info (click to toggle)
libsession-token-perl 1.503-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 196 kB
  • sloc: ansic: 166; perl: 90; makefile: 3
file content (131 lines) | stat: -rw-r--r-- 2,669 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "standard.h"
#include "rand.h"

#include <stdlib.h>
#include <string.h>
#include <assert.h>


struct session_token_ctx {
  int mask;
  int count;
  int curr_word;
  int bytes_left_in_curr_word;
  struct randctx isaac_ctx;
  char *alphabet;
  size_t alphabet_length;
  size_t token_length;
};

typedef struct session_token_ctx * Session_Token;

static inline int get_new_byte(struct session_token_ctx *ctx) {
  int output;

  if (ctx->bytes_left_in_curr_word == 0) {
    if (ctx->count > 255) {
      isaac(&ctx->isaac_ctx);
      ctx->count = 0;
    }

    ctx->curr_word = ctx->isaac_ctx.randrsl[ctx->count];
    ctx->count++;
    ctx->bytes_left_in_curr_word = 4;
  }

  output = ctx->curr_word & 0xFF;
  ctx->bytes_left_in_curr_word--;
  ctx->curr_word >>= 8;

  return output;
}

static int get_mask(int v) {
  v--;
  v |= v >> 1;
  v |= v >> 2;
  v |= v >> 4;
  return v;
}


MODULE = Session::Token		PACKAGE = Session::Token		

PROTOTYPES: ENABLE


Session_Token
_new_context(seed, alphabet, token_length)
        SV *seed
        SV *alphabet
        size_t token_length
    CODE:
        struct session_token_ctx *ctx;
        char *seedp;
        size_t len;

        len = SvCUR(seed);
        seedp = SvPV(seed, len);

        assert(sizeof(ctx->isaac_ctx.randrsl) == 1024);

        if (len != 1024) {
          croak("unexpected seed length: %lu", len);
        }

        ctx = malloc(sizeof(struct session_token_ctx));
        memset(ctx, '\0', sizeof(struct session_token_ctx));

        memcpy(&ctx->isaac_ctx.randrsl, seedp, 1024);
        randinit(&ctx->isaac_ctx, TRUE);
        isaac(&ctx->isaac_ctx);

        ctx->alphabet_length = SvCUR(alphabet);
        ctx->alphabet = malloc(ctx->alphabet_length);
        memcpy(ctx->alphabet, SvPV(alphabet, ctx->alphabet_length), ctx->alphabet_length);

        ctx->token_length = token_length;

        ctx->mask = get_mask(ctx->alphabet_length);

        RETVAL = ctx;

    OUTPUT:
        RETVAL


void
DESTROY(ctx)
        Session_Token ctx
    CODE:
        free(ctx->alphabet);
        free(ctx);


SV *
get(ctx)
        Session_Token ctx
    CODE:
        SV *output;
        char *outputp;
        size_t i, curr;

        output = newSVpvn("", 0);
        SvGROW(output, ctx->token_length);
        SvCUR_set(output, ctx->token_length);
        outputp = SvPV(output, ctx->token_length);

        for (i=0; i<ctx->token_length; i++) {
          while((curr = (get_new_byte(ctx) & ctx->mask)) >= ctx->alphabet_length)  ;
          outputp[i] = ctx->alphabet[curr];
        }

        RETVAL = output;

    OUTPUT:
        RETVAL