advapi32: Implement and test SystemFunction002 (DES decrypt).
[wine] / dlls / advapi32 / crypt_arc4.c
1 /*
2  *  Copyright 2006 Mike McCormack
3  *
4  *  based on arc4.cpp - written and placed in the public domain by Wei Dai
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2.1 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /* http://cryptopp.sourceforge.net/docs/ref521/arc4_8cpp-source.html */
22
23 #include <stdarg.h>
24
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "windef.h"
28 #include "winternl.h"
29
30 typedef struct tag_arc4_info {
31     unsigned char state[256];
32     unsigned char x, y;
33 } arc4_info;
34
35 static void arc4_init(arc4_info *a4i, const BYTE *key, unsigned int keyLen)
36 {
37     unsigned int keyIndex = 0, stateIndex = 0;
38     unsigned int i, a;
39
40     a4i->x = a4i->y = 0;
41
42     for (i=0; i<256; i++)
43         a4i->state[i] = i;
44
45     for (i=0; i<256; i++)
46     {
47         a = a4i->state[i];
48         stateIndex += key[keyIndex] + a;
49         stateIndex &= 0xff;
50         a4i->state[i] = a4i->state[stateIndex];
51         a4i->state[stateIndex] = a;
52         if (++keyIndex >= keyLen)
53             keyIndex = 0;
54     }
55 }
56
57 static void arc4_ProcessString(arc4_info *a4i, BYTE *inoutString, unsigned int length)
58 {
59     BYTE *const s=a4i->state;
60     unsigned int x = a4i->x;
61     unsigned int y = a4i->y;
62     unsigned int a, b;
63
64     while(length--)
65     {
66         x = (x+1) & 0xff;
67         a = s[x];
68         y = (y+a) & 0xff;
69         b = s[y];
70         s[x] = b;
71         s[y] = a;
72         *inoutString++ ^= s[(a+b) & 0xff];
73     }
74
75     a4i->x = x;
76     a4i->y = y;
77 }
78
79 struct ustring {
80     DWORD Length;
81     DWORD MaximumLength;
82     unsigned char *Buffer;
83 };
84
85 /******************************************************************************
86  * SystemFunction032  [ADVAPI32.@]
87  *
88  * Encrypts a string data using ARC4
89  *
90  * PARAMS
91  *   data    [I/O] data to encrypt
92  *   key     [I] key data
93  *
94  * RETURNS
95  *  Success: STATUS_SUCCESS
96  *  Failure: STATUS_UNSUCCESSFUL
97  *
98  * NOTES
99  *  see http://web.it.kth.se/~rom/ntsec.html#crypto-strongavail
100  */
101 NTSTATUS WINAPI SystemFunction032(struct ustring *data, struct ustring *key)
102 {
103     arc4_info a4i;
104
105     arc4_init(&a4i, key->Buffer, key->Length);
106     arc4_ProcessString(&a4i, data->Buffer, data->Length);
107
108     return STATUS_SUCCESS;
109 }