9 #include "crypto/crypto.h"
11 #define RSA_MIN_PADLEN 8
12 #define MAX_KEYLEN 512
15 int keylen
; /* length of modulus in bytes */
16 BI_CTX
*bi_ctx
; /* bigint context */
18 bigint
*n
; /* modulus */
19 bigint
*e
; /* public exponent */
20 bigint
*d
; /* private exponent */
22 int use_crt
; /* use chinese remainder theorem */
23 bigint
*p
; /* p as in m = pq */
24 bigint
*q
; /* q as in m = pq */
25 bigint
*dP
; /* d mod (p-1) */
26 bigint
*dQ
; /* d mod (q-1) */
27 bigint
*qInv
; /* q^-1 mod p */
33 rsakey_init(const unsigned char *modulus
, int mod_len
,
34 const unsigned char *pub_exp
, int pub_len
,
35 const unsigned char *priv_exp
, int priv_len
,
36 /* Optional, used for crt optimization */
37 const unsigned char *p
, int p_len
,
38 const unsigned char *q
, int q_len
,
39 const unsigned char *dP
, int dP_len
,
40 const unsigned char *dQ
, int dQ_len
,
41 const unsigned char *qInv
, int qInv_len
)
46 if (mod_len
> MAX_KEYLEN
) {
50 rsakey
= calloc(1, sizeof(rsakey_t
));
54 rsakey
->base64
= base64_init(NULL
, 0, 0);
55 if (!rsakey
->base64
) {
60 /* Initialize structure */
61 for (i
=0; !modulus
[i
] && i
<mod_len
; i
++);
62 rsakey
->keylen
= mod_len
-i
;
63 rsakey
->bi_ctx
= bi_initialize();
65 /* Import public and private keys */
66 rsakey
->n
= bi_import(rsakey
->bi_ctx
, modulus
, mod_len
);
67 rsakey
->e
= bi_import(rsakey
->bi_ctx
, pub_exp
, pub_len
);
68 rsakey
->d
= bi_import(rsakey
->bi_ctx
, priv_exp
, priv_len
);
70 if (p
&& q
&& dP
&& dQ
&& qInv
) {
71 /* Import crt optimization keys */
72 rsakey
->p
= bi_import(rsakey
->bi_ctx
, p
, p_len
);
73 rsakey
->q
= bi_import(rsakey
->bi_ctx
, q
, q_len
);
74 rsakey
->dP
= bi_import(rsakey
->bi_ctx
, dP
, dP_len
);
75 rsakey
->dQ
= bi_import(rsakey
->bi_ctx
, dQ
, dQ_len
);
76 rsakey
->qInv
= bi_import(rsakey
->bi_ctx
, qInv
, qInv_len
);
78 /* Set imported keys either permanent or modulo */
79 bi_permanent(rsakey
->dP
);
80 bi_permanent(rsakey
->dQ
);
81 bi_permanent(rsakey
->qInv
);
82 bi_set_mod(rsakey
->bi_ctx
, rsakey
->p
, BIGINT_P_OFFSET
);
83 bi_set_mod(rsakey
->bi_ctx
, rsakey
->q
, BIGINT_Q_OFFSET
);
88 /* Add keys to the bigint context */
89 bi_set_mod(rsakey
->bi_ctx
, rsakey
->n
, BIGINT_M_OFFSET
);
90 bi_permanent(rsakey
->e
);
91 bi_permanent(rsakey
->d
);
96 rsakey_init_pem(const char *pemstr
)
99 unsigned char *modulus
=NULL
; unsigned int mod_len
=0;
100 unsigned char *pub_exp
=NULL
; unsigned int pub_len
=0;
101 unsigned char *priv_exp
=NULL
; unsigned int priv_len
=0;
102 unsigned char *p
=NULL
; unsigned int p_len
=0;
103 unsigned char *q
=NULL
; unsigned int q_len
=0;
104 unsigned char *dP
=NULL
; unsigned int dP_len
=0;
105 unsigned char *dQ
=NULL
; unsigned int dQ_len
=0;
106 unsigned char *qInv
=NULL
; unsigned int qInv_len
=0;
107 rsakey_t
*rsakey
=NULL
;
109 rsapem
= rsapem_init(pemstr
);
114 /* Read public and private keys */
115 mod_len
= rsapem_read_vector(rsapem
, &modulus
);
116 pub_len
= rsapem_read_vector(rsapem
, &pub_exp
);
117 priv_len
= rsapem_read_vector(rsapem
, &priv_exp
);
118 /* Read private keys for crt optimization */
119 p_len
= rsapem_read_vector(rsapem
, &p
);
120 q_len
= rsapem_read_vector(rsapem
, &q
);
121 dP_len
= rsapem_read_vector(rsapem
, &dP
);
122 dQ_len
= rsapem_read_vector(rsapem
, &dQ
);
123 qInv_len
= rsapem_read_vector(rsapem
, &qInv
);
125 if (modulus
&& pub_exp
&& priv_exp
) {
126 /* Initialize rsakey value */
127 rsakey
= rsakey_init(modulus
, mod_len
, pub_exp
, pub_len
, priv_exp
, priv_len
,
128 p
, p_len
, q
, q_len
, dP
, dP_len
, dQ
, dQ_len
, qInv
, qInv_len
);
139 rsapem_destroy(rsapem
);
144 rsakey_destroy(rsakey_t
*rsakey
)
147 bi_free_mod(rsakey
->bi_ctx
, BIGINT_M_OFFSET
);
148 bi_depermanent(rsakey
->e
);
149 bi_depermanent(rsakey
->d
);
150 bi_free(rsakey
->bi_ctx
, rsakey
->e
);
151 bi_free(rsakey
->bi_ctx
, rsakey
->d
);
153 if (rsakey
->use_crt
) {
154 bi_free_mod(rsakey
->bi_ctx
, BIGINT_P_OFFSET
);
155 bi_free_mod(rsakey
->bi_ctx
, BIGINT_Q_OFFSET
);
156 bi_depermanent(rsakey
->dP
);
157 bi_depermanent(rsakey
->dQ
);
158 bi_depermanent(rsakey
->qInv
);
159 bi_free(rsakey
->bi_ctx
, rsakey
->dP
);
160 bi_free(rsakey
->bi_ctx
, rsakey
->dQ
);
161 bi_free(rsakey
->bi_ctx
, rsakey
->qInv
);
163 bi_terminate(rsakey
->bi_ctx
);
165 base64_destroy(rsakey
->base64
);
171 rsakey_modpow(rsakey_t
*rsakey
, bigint
*msg
)
173 if (rsakey
->use_crt
) {
174 return bi_crt(rsakey
->bi_ctx
, msg
,
175 rsakey
->dP
, rsakey
->dQ
,
176 rsakey
->p
, rsakey
->q
, rsakey
->qInv
);
178 rsakey
->bi_ctx
->mod_offset
= BIGINT_M_OFFSET
;
179 return bi_mod_power(rsakey
->bi_ctx
, msg
, rsakey
->d
);
184 rsakey_sign(rsakey_t
*rsakey
, char *dst
, int dstlen
, const char *b64digest
,
185 unsigned char *ipaddr
, int ipaddrlen
,
186 unsigned char *hwaddr
, int hwaddrlen
)
188 unsigned char buffer
[MAX_KEYLEN
];
189 unsigned char *digest
;
198 if (dstlen
< base64_encoded_length(rsakey
->base64
, rsakey
->keylen
)) {
202 /* Decode the base64 digest */
203 digestlen
= base64_decode(rsakey
->base64
, &digest
, b64digest
, strlen(b64digest
));
208 /* Calculate the input data length */
209 inputlen
= digestlen
+ipaddrlen
+hwaddrlen
;
210 if (inputlen
> rsakey
->keylen
-3-RSA_MIN_PADLEN
) {
215 /* Minimum size is 32 */
219 /* Construct the input buffer with padding */
220 /* See RFC 3447 9.2 for more information */
222 memset(buffer
, 0, sizeof(buffer
));
223 buffer
[idx
++] = 0x00;
224 buffer
[idx
++] = 0x01;
225 memset(buffer
+idx
, 0xff, rsakey
->keylen
-inputlen
-3);
226 idx
+= rsakey
->keylen
-inputlen
-3;
227 buffer
[idx
++] = 0x00;
228 memcpy(buffer
+idx
, digest
, digestlen
);
230 memcpy(buffer
+idx
, ipaddr
, ipaddrlen
);
232 memcpy(buffer
+idx
, hwaddr
, hwaddrlen
);
235 /* Calculate the signature s = m^d (mod n) */
236 bi_in
= bi_import(rsakey
->bi_ctx
, buffer
, rsakey
->keylen
);
237 bi_out
= rsakey_modpow(rsakey
, bi_in
);
239 /* Encode and save the signature into dst */
240 bi_export(rsakey
->bi_ctx
, bi_out
, buffer
, rsakey
->keylen
);
241 base64_encode(rsakey
->base64
, dst
, buffer
, rsakey
->keylen
);
247 /* Mask generation function with SHA-1 hash */
248 /* See RFC 3447 B.2.1 for more information */
250 rsakey_mfg1(unsigned char *dst
, int dstlen
, const unsigned char *seed
, int seedlen
, int masklen
)
257 iterations
= (masklen
+SHA1_SIZE
-1)/SHA1_SIZE
;
258 if (dstlen
< iterations
*SHA1_SIZE
) {
263 for (i
=0; i
<iterations
; i
++) {
264 unsigned char counter
[4];
265 counter
[0] = (i
>>24)&0xff;
266 counter
[1] = (i
>>16)&0xff;
267 counter
[2] = (i
>>8)&0xff;
271 SHA1_Update(&sha_ctx
, seed
, seedlen
);
272 SHA1_Update(&sha_ctx
, counter
, sizeof(counter
));
273 SHA1_Final(dst
+dstpos
, &sha_ctx
);
279 /* OAEP decryption with SHA-1 hash */
280 /* See RFC 3447 7.1.2 for more information */
282 rsakey_decrypt(rsakey_t
*rsakey
, unsigned char *dst
, int dstlen
, const char *b64input
)
284 unsigned char buffer
[MAX_KEYLEN
];
285 unsigned char maskbuf
[MAX_KEYLEN
];
286 unsigned char *input
;
294 if (!dst
|| !b64input
) {
298 memset(buffer
, 0, sizeof(buffer
));
299 inputlen
= base64_decode(rsakey
->base64
, &input
, b64input
, strlen(b64input
));
300 if (inputlen
< 0 || inputlen
> rsakey
->keylen
) {
303 memcpy(buffer
+rsakey
->keylen
-inputlen
, input
, inputlen
);
307 /* Decrypt the input data m = c^d (mod n) */
308 bi_in
= bi_import(rsakey
->bi_ctx
, buffer
, rsakey
->keylen
);
309 bi_out
= rsakey_modpow(rsakey
, bi_in
);
311 memset(buffer
, 0, sizeof(buffer
));
312 bi_export(rsakey
->bi_ctx
, bi_out
, buffer
, rsakey
->keylen
);
314 /* First unmask seed in the buffer */
315 ret
= rsakey_mfg1(maskbuf
, sizeof(maskbuf
),
317 rsakey
->keylen
-1-SHA1_SIZE
,
322 for (i
=0; i
<ret
; i
++) {
323 buffer
[1+i
] ^= maskbuf
[i
];
326 /* Then unmask the actual message */
327 ret
= rsakey_mfg1(maskbuf
, sizeof(maskbuf
),
329 rsakey
->keylen
-1-SHA1_SIZE
);
333 for (i
=0; i
<ret
; i
++) {
334 buffer
[1+SHA1_SIZE
+i
] ^= maskbuf
[i
];
337 /* Finally find the first data byte */
338 for (i
=1+2*SHA1_SIZE
; i
<rsakey
->keylen
&& !buffer
[i
++];);
340 /* Calculate real output length and return */
341 outlen
= rsakey
->keylen
-i
;
342 if (outlen
> dstlen
) {
345 memcpy(dst
, buffer
+i
, outlen
);
350 rsakey_parseiv(rsakey_t
*rsakey
, unsigned char *dst
, int dstlen
, const char *b64input
)
352 unsigned char *tmpptr
;
356 if (!dst
|| !b64input
) {
360 length
= base64_decode(rsakey
->base64
, &tmpptr
, b64input
, strlen(b64input
));
363 } else if (length
> dstlen
) {
368 memcpy(dst
, tmpptr
, length
);