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