2 * Copyright (C) 2011-2012 Juho Vähä-Herttua
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
23 #include "crypto/crypto.h"
25 #define RSA_MIN_PADLEN 8
26 #define MAX_KEYLEN 512
29 int keylen
; /* length of modulus in bytes */
30 BI_CTX
*bi_ctx
; /* bigint context */
32 bigint
*n
; /* modulus */
33 bigint
*e
; /* public exponent */
34 bigint
*d
; /* private exponent */
36 int use_crt
; /* use chinese remainder theorem */
37 bigint
*p
; /* p as in m = pq */
38 bigint
*q
; /* q as in m = pq */
39 bigint
*dP
; /* d mod (p-1) */
40 bigint
*dQ
; /* d mod (q-1) */
41 bigint
*qInv
; /* q^-1 mod p */
47 rsakey_init(const unsigned char *modulus
, int mod_len
,
48 const unsigned char *pub_exp
, int pub_len
,
49 const unsigned char *priv_exp
, int priv_len
,
50 /* Optional, used for crt optimization */
51 const unsigned char *p
, int p_len
,
52 const unsigned char *q
, int q_len
,
53 const unsigned char *dP
, int dP_len
,
54 const unsigned char *dQ
, int dQ_len
,
55 const unsigned char *qInv
, int qInv_len
)
60 if (mod_len
> MAX_KEYLEN
) {
64 rsakey
= calloc(1, sizeof(rsakey_t
));
68 rsakey
->base64
= base64_init(NULL
, 0, 0);
69 if (!rsakey
->base64
) {
74 /* Initialize structure */
75 for (i
=0; !modulus
[i
] && i
<mod_len
; i
++);
76 rsakey
->keylen
= mod_len
-i
;
77 rsakey
->bi_ctx
= bi_initialize();
79 /* Import public and private keys */
80 rsakey
->n
= bi_import(rsakey
->bi_ctx
, modulus
, mod_len
);
81 rsakey
->e
= bi_import(rsakey
->bi_ctx
, pub_exp
, pub_len
);
82 rsakey
->d
= bi_import(rsakey
->bi_ctx
, priv_exp
, priv_len
);
84 if (p
&& q
&& dP
&& dQ
&& qInv
) {
85 /* Import crt optimization keys */
86 rsakey
->p
= bi_import(rsakey
->bi_ctx
, p
, p_len
);
87 rsakey
->q
= bi_import(rsakey
->bi_ctx
, q
, q_len
);
88 rsakey
->dP
= bi_import(rsakey
->bi_ctx
, dP
, dP_len
);
89 rsakey
->dQ
= bi_import(rsakey
->bi_ctx
, dQ
, dQ_len
);
90 rsakey
->qInv
= bi_import(rsakey
->bi_ctx
, qInv
, qInv_len
);
92 /* Set imported keys either permanent or modulo */
93 bi_permanent(rsakey
->dP
);
94 bi_permanent(rsakey
->dQ
);
95 bi_permanent(rsakey
->qInv
);
96 bi_set_mod(rsakey
->bi_ctx
, rsakey
->p
, BIGINT_P_OFFSET
);
97 bi_set_mod(rsakey
->bi_ctx
, rsakey
->q
, BIGINT_Q_OFFSET
);
102 /* Add keys to the bigint context */
103 bi_set_mod(rsakey
->bi_ctx
, rsakey
->n
, BIGINT_M_OFFSET
);
104 bi_permanent(rsakey
->e
);
105 bi_permanent(rsakey
->d
);
110 rsakey_init_pem(const char *pemstr
)
113 unsigned char *modulus
=NULL
; unsigned int mod_len
=0;
114 unsigned char *pub_exp
=NULL
; unsigned int pub_len
=0;
115 unsigned char *priv_exp
=NULL
; unsigned int priv_len
=0;
116 unsigned char *p
=NULL
; unsigned int p_len
=0;
117 unsigned char *q
=NULL
; unsigned int q_len
=0;
118 unsigned char *dP
=NULL
; unsigned int dP_len
=0;
119 unsigned char *dQ
=NULL
; unsigned int dQ_len
=0;
120 unsigned char *qInv
=NULL
; unsigned int qInv_len
=0;
121 rsakey_t
*rsakey
=NULL
;
123 rsapem
= rsapem_init(pemstr
);
128 /* Read public and private keys */
129 mod_len
= rsapem_read_vector(rsapem
, &modulus
);
130 pub_len
= rsapem_read_vector(rsapem
, &pub_exp
);
131 priv_len
= rsapem_read_vector(rsapem
, &priv_exp
);
132 /* Read private keys for crt optimization */
133 p_len
= rsapem_read_vector(rsapem
, &p
);
134 q_len
= rsapem_read_vector(rsapem
, &q
);
135 dP_len
= rsapem_read_vector(rsapem
, &dP
);
136 dQ_len
= rsapem_read_vector(rsapem
, &dQ
);
137 qInv_len
= rsapem_read_vector(rsapem
, &qInv
);
139 if (modulus
&& pub_exp
&& priv_exp
) {
140 /* Initialize rsakey value */
141 rsakey
= rsakey_init(modulus
, mod_len
, pub_exp
, pub_len
, priv_exp
, priv_len
,
142 p
, p_len
, q
, q_len
, dP
, dP_len
, dQ
, dQ_len
, qInv
, qInv_len
);
153 rsapem_destroy(rsapem
);
158 rsakey_destroy(rsakey_t
*rsakey
)
161 bi_free_mod(rsakey
->bi_ctx
, BIGINT_M_OFFSET
);
162 bi_depermanent(rsakey
->e
);
163 bi_depermanent(rsakey
->d
);
164 bi_free(rsakey
->bi_ctx
, rsakey
->e
);
165 bi_free(rsakey
->bi_ctx
, rsakey
->d
);
167 if (rsakey
->use_crt
) {
168 bi_free_mod(rsakey
->bi_ctx
, BIGINT_P_OFFSET
);
169 bi_free_mod(rsakey
->bi_ctx
, BIGINT_Q_OFFSET
);
170 bi_depermanent(rsakey
->dP
);
171 bi_depermanent(rsakey
->dQ
);
172 bi_depermanent(rsakey
->qInv
);
173 bi_free(rsakey
->bi_ctx
, rsakey
->dP
);
174 bi_free(rsakey
->bi_ctx
, rsakey
->dQ
);
175 bi_free(rsakey
->bi_ctx
, rsakey
->qInv
);
177 bi_terminate(rsakey
->bi_ctx
);
179 base64_destroy(rsakey
->base64
);
185 rsakey_modpow(rsakey_t
*rsakey
, bigint
*msg
)
187 if (rsakey
->use_crt
) {
188 return bi_crt(rsakey
->bi_ctx
, msg
,
189 rsakey
->dP
, rsakey
->dQ
,
190 rsakey
->p
, rsakey
->q
, rsakey
->qInv
);
192 rsakey
->bi_ctx
->mod_offset
= BIGINT_M_OFFSET
;
193 return bi_mod_power(rsakey
->bi_ctx
, msg
, rsakey
->d
);
198 rsakey_sign(rsakey_t
*rsakey
, char *dst
, int dstlen
, const char *b64digest
,
199 unsigned char *ipaddr
, int ipaddrlen
,
200 unsigned char *hwaddr
, int hwaddrlen
)
202 unsigned char buffer
[MAX_KEYLEN
];
203 unsigned char *digest
;
212 if (dstlen
< base64_encoded_length(rsakey
->base64
, rsakey
->keylen
)) {
216 /* Decode the base64 digest */
217 digestlen
= base64_decode(rsakey
->base64
, &digest
, b64digest
, strlen(b64digest
));
222 /* Calculate the input data length */
223 inputlen
= digestlen
+ipaddrlen
+hwaddrlen
;
224 if (inputlen
> rsakey
->keylen
-3-RSA_MIN_PADLEN
) {
229 /* Minimum size is 32 */
233 /* Construct the input buffer with padding */
234 /* See RFC 3447 9.2 for more information */
236 memset(buffer
, 0, sizeof(buffer
));
237 buffer
[idx
++] = 0x00;
238 buffer
[idx
++] = 0x01;
239 memset(buffer
+idx
, 0xff, rsakey
->keylen
-inputlen
-3);
240 idx
+= rsakey
->keylen
-inputlen
-3;
241 buffer
[idx
++] = 0x00;
242 memcpy(buffer
+idx
, digest
, digestlen
);
244 memcpy(buffer
+idx
, ipaddr
, ipaddrlen
);
246 memcpy(buffer
+idx
, hwaddr
, hwaddrlen
);
249 /* Calculate the signature s = m^d (mod n) */
250 bi_in
= bi_import(rsakey
->bi_ctx
, buffer
, rsakey
->keylen
);
251 bi_out
= rsakey_modpow(rsakey
, bi_in
);
253 /* Encode and save the signature into dst */
254 bi_export(rsakey
->bi_ctx
, bi_out
, buffer
, rsakey
->keylen
);
255 base64_encode(rsakey
->base64
, dst
, buffer
, rsakey
->keylen
);
261 /* Mask generation function with SHA-1 hash */
262 /* See RFC 3447 B.2.1 for more information */
264 rsakey_mfg1(unsigned char *dst
, int dstlen
, const unsigned char *seed
, int seedlen
, int masklen
)
271 iterations
= (masklen
+SHA1_SIZE
-1)/SHA1_SIZE
;
272 if (dstlen
< iterations
*SHA1_SIZE
) {
277 for (i
=0; i
<iterations
; i
++) {
278 unsigned char counter
[4];
279 counter
[0] = (i
>>24)&0xff;
280 counter
[1] = (i
>>16)&0xff;
281 counter
[2] = (i
>>8)&0xff;
285 SHA1_Update(&sha_ctx
, seed
, seedlen
);
286 SHA1_Update(&sha_ctx
, counter
, sizeof(counter
));
287 SHA1_Final(dst
+dstpos
, &sha_ctx
);
293 /* OAEP decryption with SHA-1 hash */
294 /* See RFC 3447 7.1.2 for more information */
296 rsakey_decrypt(rsakey_t
*rsakey
, unsigned char *dst
, int dstlen
, const char *b64input
)
298 unsigned char buffer
[MAX_KEYLEN
];
299 unsigned char maskbuf
[MAX_KEYLEN
];
300 unsigned char *input
;
308 if (!dst
|| !b64input
) {
312 memset(buffer
, 0, sizeof(buffer
));
313 inputlen
= base64_decode(rsakey
->base64
, &input
, b64input
, strlen(b64input
));
314 if (inputlen
< 0 || inputlen
> rsakey
->keylen
) {
317 memcpy(buffer
+rsakey
->keylen
-inputlen
, input
, inputlen
);
321 /* Decrypt the input data m = c^d (mod n) */
322 bi_in
= bi_import(rsakey
->bi_ctx
, buffer
, rsakey
->keylen
);
323 bi_out
= rsakey_modpow(rsakey
, bi_in
);
325 memset(buffer
, 0, sizeof(buffer
));
326 bi_export(rsakey
->bi_ctx
, bi_out
, buffer
, rsakey
->keylen
);
328 /* First unmask seed in the buffer */
329 ret
= rsakey_mfg1(maskbuf
, sizeof(maskbuf
),
331 rsakey
->keylen
-1-SHA1_SIZE
,
336 for (i
=0; i
<ret
; i
++) {
337 buffer
[1+i
] ^= maskbuf
[i
];
340 /* Then unmask the actual message */
341 ret
= rsakey_mfg1(maskbuf
, sizeof(maskbuf
),
343 rsakey
->keylen
-1-SHA1_SIZE
);
347 for (i
=0; i
<ret
; i
++) {
348 buffer
[1+SHA1_SIZE
+i
] ^= maskbuf
[i
];
351 /* Finally find the first data byte */
352 for (i
=1+2*SHA1_SIZE
; i
<rsakey
->keylen
&& !buffer
[i
++];);
354 /* Calculate real output length and return */
355 outlen
= rsakey
->keylen
-i
;
356 if (outlen
> dstlen
) {
359 memcpy(dst
, buffer
+i
, outlen
);
364 rsakey_parseiv(rsakey_t
*rsakey
, unsigned char *dst
, int dstlen
, const char *b64input
)
366 unsigned char *tmpptr
;
370 if (!dst
|| !b64input
) {
374 length
= base64_decode(rsakey
->base64
, &tmpptr
, b64input
, strlen(b64input
));
377 } else if (length
> dstlen
) {
382 memcpy(dst
, tmpptr
, length
);