1 /* crypto-rc4.c draft-brezak-win2k-krb-rc4-hmac-04 crypto functions
2 * Copyright (C) 2003 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 rc4_hmac_encrypt (Shishi
* handle
,
32 char **ivout
, size_t * ivoutlen
,
33 const char *in
, size_t inlen
, char **out
, size_t * outlen
)
36 char L40
[14] = "fortybits";
37 char SK
= "signaturekey";
40 T
[0] = keyusage
& 0xFF;
41 T
[1] = (keyusage
>> 8) & 0xFF;
42 T
[2] = (keyusage
>> 16) & 0xFF;
43 T
[3] = (keyusage
>> 24) & 0xFF;
45 if (shishi_key_type (key
) == SHISHI_RC4_HMAC_EXP
)
47 memcpy (L40
+ 10, T
, 4);
48 HMAC (K
, L40
, 10 + 4, K1
);
56 memset (K1
+ 7, 0xAB, 9);
58 nonce (edata
.Confounder
, 8);
59 memcpy (edata
.Data
, data
);
61 edata
.Checksum
= HMAC (K2
, edata
);
62 K3
= HMAC (K1
, edata
.Checksum
);
64 RC4 (K3
, edata
.Confounder
);
72 rc4_hmac_decrypt (Shishi
* handle
,
77 char **ivout
, size_t * ivoutlen
,
78 const char *in
, size_t inlen
, char **out
, size_t * outlen
)
84 rc4_hmac_exp_encrypt (Shishi
* handle
,
89 char **ivout
, size_t * ivoutlen
,
90 const char *in
, size_t inlen
,
91 char **out
, size_t * outlen
)
96 rc4_hmac_exp_decrypt (Shishi
* handle
,
101 char **ivout
, size_t * ivoutlen
,
102 const char *in
, size_t inlen
,
103 char **out
, size_t * outlen
)
107 #define RC4_HMAC_CKSUM_KEY_DERIVE_CONSTANT "signaturekey"
110 rc4_hmac_md5_checksum (Shishi
* handle
,
114 const char *in
, size_t inlen
,
115 char **out
, size_t * outlen
)
119 gcry_md_hd_t mdh
, mdh2
;
120 int halg
= GCRY_MD_MD5
;
121 size_t hlen
= gcry_md_get_algo_dlen (halg
);
126 T
[0] = keyusage
& 0xFF;
127 T
[1] = (keyusage
>> 8) & 0xFF;
128 T
[2] = (keyusage
>> 16) & 0xFF;
129 T
[3] = (keyusage
>> 24) & 0xFF;
131 err
= gcry_md_open (&mdh
, halg
, GCRY_MD_FLAG_HMAC
);
132 if (err
!= GPG_ERR_NO_ERROR
)
134 shishi_error_printf (handle
, "Libgcrypt md open failed");
135 shishi_error_set (handle
, gpg_strerror (err
));
136 return SHISHI_CRYPTO_INTERNAL_ERROR
;
139 err
= gcry_md_setkey (mdh
, shishi_key_value (key
), shishi_key_length (key
));
140 if (err
!= GPG_ERR_NO_ERROR
)
142 shishi_error_printf (handle
, "Libgcrypt md setkey failed");
143 shishi_error_set (handle
, gpg_strerror (err
));
144 return SHISHI_CRYPTO_INTERNAL_ERROR
;
147 gcry_md_write (mdh
, RC4_HMAC_CKSUM_KEY_DERIVE_CONSTANT
,
148 strlen (RC4_HMAC_CKSUM_KEY_DERIVE_CONSTANT
) + 1);
150 err
= gcry_md_open (&mdh2
, halg
, GCRY_MD_FLAG_HMAC
);
151 if (err
!= GPG_ERR_NO_ERROR
)
153 shishi_error_printf (handle
, "Libgcrypt md open failed");
154 shishi_error_set (handle
, gpg_strerror (err
));
155 return SHISHI_CRYPTO_INTERNAL_ERROR
;
158 err
= gcry_md_setkey (mdh2
, gcry_md_read (mdh
, halg
), hlen
);
159 if (err
!= GPG_ERR_NO_ERROR
)
161 shishi_error_printf (handle
, "Libgcrypt md setkey failed");
162 shishi_error_set (handle
, gpg_strerror (err
));
163 return SHISHI_CRYPTO_INTERNAL_ERROR
;
168 gcry_md_write (mdh2
, T
, 4);
169 gcry_md_write (mdh2
, in
, inlen
);
171 hash
= gcry_md_read (mdh2
, halg
);
174 shishi_error_printf (handle
, "Libgcrypt failed to compute hash");
175 return SHISHI_CRYPTO_INTERNAL_ERROR
;
179 *out
= xmemdup (hash
, *outlen
);
181 gcry_md_close (mdh2
);
183 struct hmac_md5_ctx ctx
;
184 char Ksign
[MD5_DIGEST_SIZE
];
187 T
[0] = keyusage
& 0xFF;
188 T
[1] = (keyusage
>> 8) & 0xFF;
189 T
[2] = (keyusage
>> 16) & 0xFF;
190 T
[3] = (keyusage
>> 24) & 0xFF;
192 hmac_md5_set_key (&ctx
, shishi_key_length (key
), shishi_key_value (key
));
193 hmac_md5_update (&ctx
, strlen (RC4_HMAC_CKSUM_KEY_DERIVE_CONSTANT
) + 1,
194 RC4_HMAC_CKSUM_KEY_DERIVE_CONSTANT
);
195 hmac_md5_digest (&ctx
, MD5_DIGEST_SIZE
, Ksign
);
197 hmac_md5_set_key (&ctx
, MD5_DIGEST_SIZE
, Ksign
);
199 hmac_md5_update (&ctx
, 4, T
);
200 hmac_md5_update (&ctx
, inlen
, in
);
202 *outlen
= MD5_DIGEST_SIZE
;
203 *out
= xmalloc (*outlen
);
205 hmac_md5_digest (&ctx
, *outlen
, *out
);
212 rc4_hmac_random_to_key (Shishi
* handle
,
213 const char *random
, size_t randomlen
,
216 if (randomlen
!= shishi_key_length (outkey
))
218 shishi_error_printf (handle
, "RC4 random to key caller error");
219 return SHISHI_CRYPTO_ERROR
;
222 shishi_key_value_set (outkey
, random
);
228 rc4_hmac_string_to_key (Shishi
* handle
,
233 const char *parameter
, Shishi_key
* outkey
)
239 tmplen
= 2 * stringlen
;
240 tmp
= xmalloc (tmplen
);
242 for (i
= 0; i
< stringlen
; i
++)
244 tmp
[2 * i
] = string
[i
];
245 tmp
[2 * i
+ 1] = '\x0';
248 rc
= shishi_md4 (handle
, tmp
, tmplen
, &md
);
253 shishi_key_value_set (outkey
, md
);
258 cipherinfo rc4_hmac_info
= {
267 rc4_hmac_random_to_key
,
268 rc4_hmac_string_to_key
,
273 cipherinfo rc4_hmac_exp_info
= {
282 rc4_hmac_random_to_key
,
283 rc4_hmac_string_to_key
,
284 rc4_hmac_exp_encrypt
,
288 checksuminfo rc4_hmac_md5_info
= {
292 rc4_hmac_md5_checksum