FreeRDP
rc4.c
1 
20 #include <winpr/assert.h>
21 
22 #include "rc4.h"
23 
24 #define CTX_SIZE 256
25 
26 struct winpr_int_rc4_ctx
27 {
28  size_t i;
29  size_t j;
30  BYTE s[CTX_SIZE];
31  BYTE t[CTX_SIZE];
32 };
33 
34 static void swap(BYTE* p1, BYTE* p2)
35 {
36  BYTE t = *p1;
37  *p1 = *p2;
38  *p2 = t;
39 }
40 
41 winpr_int_RC4_CTX* winpr_int_rc4_new(const BYTE* key, size_t keylength)
42 {
43  winpr_int_RC4_CTX* ctx = calloc(1, sizeof(winpr_int_RC4_CTX));
44  if (!ctx)
45  return NULL;
46 
47  for (size_t i = 0; i < CTX_SIZE; i++)
48  {
49  ctx->s[i] = i;
50  ctx->t[i] = key[i % keylength];
51  }
52 
53  size_t j = 0;
54  for (size_t i = 0; i < CTX_SIZE; i++)
55  {
56  j = (j + ctx->s[i] + ctx->t[i]) % CTX_SIZE;
57  swap(&ctx->s[i], &ctx->s[j]);
58  }
59  return ctx;
60 }
61 
62 void winpr_int_rc4_free(winpr_int_RC4_CTX* ctx)
63 {
64  free(ctx);
65 }
66 
67 BOOL winpr_int_rc4_update(winpr_int_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output)
68 {
69  WINPR_ASSERT(ctx);
70 
71  size_t t1 = ctx->i;
72  size_t t2 = ctx->j;
73  for (size_t i = 0; i < length; i++)
74  {
75  t1 = (t1 + 1) % CTX_SIZE;
76  t2 = (t2 + ctx->s[t1]) % CTX_SIZE;
77  swap(&ctx->s[t1], &ctx->s[t2]);
78 
79  const size_t idx = ((size_t)ctx->s[t1] + ctx->s[t2]) % CTX_SIZE;
80  const BYTE val = ctx->s[idx];
81  const BYTE out = *input++ ^ val;
82  *output++ = out;
83  }
84 
85  ctx->i = t1;
86  ctx->j = t2;
87  return TRUE;
88 }