]>
Commit | Line | Data |
---|---|---|
552cc11b | 1 | /* |
7033a70f | 2 | * Copyright (C) 2005-2009 Martin Willi |
552cc11b MW |
3 | * Copyright (C) 2005 Jan Hutter |
4 | * Hochschule fuer Technik Rapperswil | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or (at your | |
9 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
13 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | * for more details. | |
552cc11b | 15 | */ |
7daf5226 | 16 | |
552cc11b MW |
17 | #include <gmp.h> |
18 | #include <sys/stat.h> | |
19 | #include <unistd.h> | |
20 | #include <stdio.h> | |
21 | #include <string.h> | |
22 | ||
23 | #include "gmp_rsa_public_key.h" | |
24 | ||
f05b4272 | 25 | #include <utils/debug.h> |
d3d7e46b | 26 | #include <asn1/oid.h> |
552cc11b | 27 | #include <asn1/asn1.h> |
d3d7e46b | 28 | #include <asn1/asn1_parser.h> |
d3d7e46b | 29 | #include <crypto/hashers/hasher.h> |
552cc11b | 30 | |
3e35a6e7 MW |
31 | #ifdef HAVE_MPZ_POWM_SEC |
32 | # undef mpz_powm | |
33 | # define mpz_powm mpz_powm_sec | |
34 | #endif | |
35 | ||
552cc11b MW |
36 | typedef struct private_gmp_rsa_public_key_t private_gmp_rsa_public_key_t; |
37 | ||
38 | /** | |
39 | * Private data structure with signing context. | |
40 | */ | |
41 | struct private_gmp_rsa_public_key_t { | |
42 | /** | |
43 | * Public interface for this signer. | |
44 | */ | |
45 | gmp_rsa_public_key_t public; | |
7daf5226 | 46 | |
552cc11b MW |
47 | /** |
48 | * Public modulus. | |
49 | */ | |
50 | mpz_t n; | |
7daf5226 | 51 | |
552cc11b MW |
52 | /** |
53 | * Public exponent. | |
54 | */ | |
55 | mpz_t e; | |
7daf5226 | 56 | |
552cc11b MW |
57 | /** |
58 | * Keysize in bytes. | |
59 | */ | |
60 | size_t k; | |
7daf5226 | 61 | |
552cc11b MW |
62 | /** |
63 | * reference counter | |
64 | */ | |
65 | refcount_t ref; | |
66 | }; | |
67 | ||
8b799d55 AS |
68 | /** |
69 | * Shared functions defined in gmp_rsa_private_key.c | |
70 | */ | |
71 | extern chunk_t gmp_mpz_to_chunk(const mpz_t value); | |
8b799d55 | 72 | |
552cc11b MW |
73 | /** |
74 | * RSAEP algorithm specified in PKCS#1. | |
75 | */ | |
76 | static chunk_t rsaep(private_gmp_rsa_public_key_t *this, chunk_t data) | |
77 | { | |
78 | mpz_t m, c; | |
79 | chunk_t encrypted; | |
7daf5226 | 80 | |
552cc11b | 81 | mpz_init(m); |
552cc11b | 82 | mpz_import(m, data.len, 1, 1, 1, 0, data.ptr); |
7daf5226 | 83 | |
ef5c37fc TB |
84 | if (mpz_cmp_ui(m, 0) <= 0 || mpz_cmp(m, this->n) >= 0) |
85 | { /* m must be <= n-1, and while 0 is technically a valid value, it | |
86 | * doesn't really make sense here, so we filter that too */ | |
87 | mpz_clear(m); | |
88 | return chunk_empty; | |
89 | } | |
90 | ||
91 | mpz_init(c); | |
552cc11b MW |
92 | mpz_powm(c, m, this->e, this->n); |
93 | ||
73f6886a MW |
94 | encrypted.len = this->k; |
95 | encrypted.ptr = mpz_export(NULL, NULL, 1, encrypted.len, 1, 0, c); | |
96 | if (encrypted.ptr == NULL) | |
97 | { | |
98 | encrypted.len = 0; | |
99 | } | |
7daf5226 | 100 | |
552cc11b | 101 | mpz_clear(c); |
73f6886a | 102 | mpz_clear(m); |
7daf5226 | 103 | |
552cc11b MW |
104 | return encrypted; |
105 | } | |
106 | ||
107 | /** | |
108 | * RSAVP1 algorithm specified in PKCS#1. | |
109 | */ | |
110 | static chunk_t rsavp1(private_gmp_rsa_public_key_t *this, chunk_t data) | |
111 | { | |
112 | return rsaep(this, data); | |
113 | } | |
114 | ||
c3628ebc AS |
115 | /** |
116 | * ASN.1 definition of digestInfo | |
117 | */ | |
118 | static const asn1Object_t digestInfoObjects[] = { | |
119 | { 0, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ | |
120 | { 1, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */ | |
121 | { 1, "digest", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */ | |
460025e2 | 122 | { 0, "exit", ASN1_EOC, ASN1_EXIT } |
c3628ebc AS |
123 | }; |
124 | #define DIGEST_INFO 0 | |
125 | #define DIGEST_INFO_ALGORITHM 1 | |
126 | #define DIGEST_INFO_DIGEST 2 | |
c3628ebc | 127 | |
552cc11b MW |
128 | /** |
129 | * Verification of an EMPSA PKCS1 signature described in PKCS#1 | |
130 | */ | |
131 | static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this, | |
132 | hash_algorithm_t algorithm, | |
133 | chunk_t data, chunk_t signature) | |
134 | { | |
135 | chunk_t em_ori, em; | |
d3d7e46b | 136 | bool success = FALSE; |
7daf5226 | 137 | |
552cc11b MW |
138 | /* remove any preceding 0-bytes from signature */ |
139 | while (signature.len && *(signature.ptr) == 0x00) | |
140 | { | |
e7227f0b | 141 | signature = chunk_skip(signature, 1); |
552cc11b | 142 | } |
7daf5226 | 143 | |
e7227f0b | 144 | if (signature.len == 0 || signature.len > this->k) |
552cc11b | 145 | { |
060b508e | 146 | return FALSE; |
552cc11b | 147 | } |
7daf5226 | 148 | |
552cc11b MW |
149 | /* unpack signature */ |
150 | em_ori = em = rsavp1(this, signature); | |
7daf5226 | 151 | |
552cc11b | 152 | /* result should look like this: |
7daf5226 | 153 | * EM = 0x00 || 0x01 || PS || 0x00 || T. |
552cc11b MW |
154 | * PS = 0xFF padding, with length to fill em |
155 | * T = oid || hash | |
156 | */ | |
7daf5226 | 157 | |
552cc11b | 158 | /* check magic bytes */ |
ef5c37fc | 159 | if (em.len < 2 || *(em.ptr) != 0x00 || *(em.ptr+1) != 0x01) |
552cc11b MW |
160 | { |
161 | goto end; | |
162 | } | |
e7227f0b | 163 | em = chunk_skip(em, 2); |
7daf5226 | 164 | |
552cc11b MW |
165 | /* find magic 0x00 */ |
166 | while (em.len > 0) | |
167 | { | |
168 | if (*em.ptr == 0x00) | |
169 | { | |
170 | /* found magic byte, stop */ | |
e7227f0b | 171 | em = chunk_skip(em, 1); |
552cc11b MW |
172 | break; |
173 | } | |
174 | else if (*em.ptr != 0xFF) | |
175 | { | |
176 | /* bad padding, decryption failed ?!*/ | |
177 | goto end; | |
178 | } | |
e7227f0b | 179 | em = chunk_skip(em, 1); |
552cc11b MW |
180 | } |
181 | ||
182 | if (em.len == 0) | |
183 | { | |
184 | /* no digestInfo found */ | |
185 | goto end; | |
186 | } | |
187 | ||
8b799d55 AS |
188 | if (algorithm == HASH_UNKNOWN) |
189 | { /* IKEv1 signatures without digestInfo */ | |
190 | if (em.len != data.len) | |
191 | { | |
8b0e0910 TB |
192 | DBG1(DBG_LIB, "hash size in signature is %u bytes instead of" |
193 | " %u bytes", em.len, data.len); | |
8b799d55 AS |
194 | goto end; |
195 | } | |
71afe0a5 | 196 | success = memeq_const(em.ptr, data.ptr, data.len); |
8b799d55 AS |
197 | } |
198 | else | |
199 | { /* IKEv2 and X.509 certificate signatures */ | |
d3d7e46b | 200 | asn1_parser_t *parser; |
552cc11b | 201 | chunk_t object; |
d3d7e46b | 202 | int objectID; |
552cc11b MW |
203 | hash_algorithm_t hash_algorithm = HASH_UNKNOWN; |
204 | ||
8b0e0910 | 205 | DBG2(DBG_LIB, "signature verification:"); |
460025e2 | 206 | parser = asn1_parser_create(digestInfoObjects, em); |
552cc11b | 207 | |
d3d7e46b | 208 | while (parser->iterate(parser, &objectID, &object)) |
552cc11b | 209 | { |
552cc11b MW |
210 | switch (objectID) |
211 | { | |
212 | case DIGEST_INFO: | |
213 | { | |
214 | if (em.len > object.len) | |
215 | { | |
8b0e0910 TB |
216 | DBG1(DBG_LIB, "digestInfo field in signature is" |
217 | " followed by %u surplus bytes", | |
552cc11b | 218 | em.len - object.len); |
d3d7e46b | 219 | goto end_parser; |
552cc11b MW |
220 | } |
221 | break; | |
222 | } | |
223 | case DIGEST_INFO_ALGORITHM: | |
224 | { | |
d3d7e46b AS |
225 | int hash_oid = asn1_parse_algorithmIdentifier(object, |
226 | parser->get_level(parser)+1, NULL); | |
552cc11b MW |
227 | |
228 | hash_algorithm = hasher_algorithm_from_oid(hash_oid); | |
8b799d55 | 229 | if (hash_algorithm == HASH_UNKNOWN || hash_algorithm != algorithm) |
552cc11b | 230 | { |
8b0e0910 TB |
231 | DBG1(DBG_LIB, "expected hash algorithm %N, but found" |
232 | " %N (OID: %#B)", hash_algorithm_names, algorithm, | |
4f23ec78 | 233 | hash_algorithm_names, hash_algorithm, &object); |
d3d7e46b | 234 | goto end_parser; |
552cc11b MW |
235 | } |
236 | break; | |
237 | } | |
238 | case DIGEST_INFO_DIGEST: | |
239 | { | |
240 | chunk_t hash; | |
241 | hasher_t *hasher; | |
7daf5226 | 242 | |
552cc11b MW |
243 | hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm); |
244 | if (hasher == NULL) | |
245 | { | |
8b0e0910 | 246 | DBG1(DBG_LIB, "hash algorithm %N not supported", |
552cc11b | 247 | hash_algorithm_names, hash_algorithm); |
d3d7e46b | 248 | goto end_parser; |
552cc11b MW |
249 | } |
250 | ||
251 | if (object.len != hasher->get_hash_size(hasher)) | |
252 | { | |
8b0e0910 TB |
253 | DBG1(DBG_LIB, "hash size in signature is %u bytes" |
254 | " instead of %u bytes", object.len, | |
255 | hasher->get_hash_size(hasher)); | |
552cc11b | 256 | hasher->destroy(hasher); |
d3d7e46b | 257 | goto end_parser; |
552cc11b MW |
258 | } |
259 | ||
260 | /* build our own hash and compare */ | |
87dd205b MW |
261 | if (!hasher->allocate_hash(hasher, data, &hash)) |
262 | { | |
263 | hasher->destroy(hasher); | |
264 | goto end_parser; | |
265 | } | |
552cc11b | 266 | hasher->destroy(hasher); |
71afe0a5 | 267 | success = memeq_const(object.ptr, hash.ptr, hash.len); |
552cc11b MW |
268 | free(hash.ptr); |
269 | break; | |
270 | } | |
271 | default: | |
272 | break; | |
273 | } | |
552cc11b | 274 | } |
d3d7e46b AS |
275 | |
276 | end_parser: | |
277 | success &= parser->success(parser); | |
278 | parser->destroy(parser); | |
552cc11b MW |
279 | } |
280 | ||
281 | end: | |
282 | free(em_ori.ptr); | |
d3d7e46b | 283 | return success; |
552cc11b MW |
284 | } |
285 | ||
876b61e1 MW |
286 | METHOD(public_key_t, get_type, key_type_t, |
287 | private_gmp_rsa_public_key_t *this) | |
552cc11b MW |
288 | { |
289 | return KEY_RSA; | |
290 | } | |
291 | ||
876b61e1 MW |
292 | METHOD(public_key_t, verify, bool, |
293 | private_gmp_rsa_public_key_t *this, signature_scheme_t scheme, | |
294 | chunk_t data, chunk_t signature) | |
552cc11b MW |
295 | { |
296 | switch (scheme) | |
297 | { | |
8b799d55 | 298 | case SIGN_RSA_EMSA_PKCS1_NULL: |
552cc11b | 299 | return verify_emsa_pkcs1_signature(this, HASH_UNKNOWN, data, signature); |
40f2589a | 300 | case SIGN_RSA_EMSA_PKCS1_SHA2_224: |
b6f739c1 | 301 | return verify_emsa_pkcs1_signature(this, HASH_SHA224, data, signature); |
40f2589a | 302 | case SIGN_RSA_EMSA_PKCS1_SHA2_256: |
552cc11b | 303 | return verify_emsa_pkcs1_signature(this, HASH_SHA256, data, signature); |
40f2589a | 304 | case SIGN_RSA_EMSA_PKCS1_SHA2_384: |
552cc11b | 305 | return verify_emsa_pkcs1_signature(this, HASH_SHA384, data, signature); |
40f2589a | 306 | case SIGN_RSA_EMSA_PKCS1_SHA2_512: |
552cc11b | 307 | return verify_emsa_pkcs1_signature(this, HASH_SHA512, data, signature); |
40f2589a AS |
308 | case SIGN_RSA_EMSA_PKCS1_SHA3_224: |
309 | return verify_emsa_pkcs1_signature(this, HASH_SHA3_224, data, signature); | |
310 | case SIGN_RSA_EMSA_PKCS1_SHA3_256: | |
311 | return verify_emsa_pkcs1_signature(this, HASH_SHA3_256, data, signature); | |
312 | case SIGN_RSA_EMSA_PKCS1_SHA3_384: | |
313 | return verify_emsa_pkcs1_signature(this, HASH_SHA3_384, data, signature); | |
314 | case SIGN_RSA_EMSA_PKCS1_SHA3_512: | |
315 | return verify_emsa_pkcs1_signature(this, HASH_SHA3_512, data, signature); | |
316 | case SIGN_RSA_EMSA_PKCS1_SHA1: | |
317 | return verify_emsa_pkcs1_signature(this, HASH_SHA1, data, signature); | |
318 | case SIGN_RSA_EMSA_PKCS1_MD5: | |
319 | return verify_emsa_pkcs1_signature(this, HASH_MD5, data, signature); | |
552cc11b | 320 | default: |
8b0e0910 | 321 | DBG1(DBG_LIB, "signature scheme %N not supported in RSA", |
552cc11b MW |
322 | signature_scheme_names, scheme); |
323 | return FALSE; | |
324 | } | |
325 | } | |
326 | ||
741680d1 | 327 | #define MIN_PS_PADDING 8 |
c50ff68d | 328 | |
876b61e1 | 329 | METHOD(public_key_t, encrypt_, bool, |
33ddaaab MW |
330 | private_gmp_rsa_public_key_t *this, encryption_scheme_t scheme, |
331 | chunk_t plain, chunk_t *crypto) | |
552cc11b | 332 | { |
c50ff68d AS |
333 | chunk_t em; |
334 | u_char *pos; | |
5025135f | 335 | int padding; |
7b3814f7 | 336 | rng_t *rng; |
c50ff68d | 337 | |
33ddaaab | 338 | if (scheme != ENCRYPT_RSA_PKCS1) |
c50ff68d | 339 | { |
33ddaaab MW |
340 | DBG1(DBG_LIB, "encryption scheme %N not supported", |
341 | encryption_scheme_names, scheme); | |
c50ff68d AS |
342 | return FALSE; |
343 | } | |
c50ff68d AS |
344 | /* number of pseudo-random padding octets */ |
345 | padding = this->k - plain.len - 3; | |
7b3814f7 | 346 | if (padding < MIN_PS_PADDING) |
c50ff68d | 347 | { |
8b0e0910 TB |
348 | DBG1(DBG_LIB, "pseudo-random padding must be at least %d octets", |
349 | MIN_PS_PADDING); | |
c50ff68d AS |
350 | return FALSE; |
351 | } | |
33ddaaab MW |
352 | rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); |
353 | if (rng == NULL) | |
354 | { | |
355 | DBG1(DBG_LIB, "no random generator available"); | |
356 | return FALSE; | |
357 | } | |
c50ff68d AS |
358 | |
359 | /* padding according to PKCS#1 7.2.1 (RSAES-PKCS1-v1.5-ENCRYPT) */ | |
8b0e0910 TB |
360 | DBG2(DBG_LIB, "padding %u bytes of data to the rsa modulus size of" |
361 | " %u bytes", plain.len, this->k); | |
c50ff68d | 362 | em.len = this->k; |
7daf5226 | 363 | em.ptr = malloc(em.len); |
c50ff68d AS |
364 | pos = em.ptr; |
365 | *pos++ = 0x00; | |
366 | *pos++ = 0x02; | |
367 | ||
368 | /* fill with pseudo random octets */ | |
5025135f | 369 | if (!rng_get_bytes_not_zero(rng, padding, pos, TRUE)) |
c50ff68d | 370 | { |
5025135f TB |
371 | DBG1(DBG_LIB, "failed to allocate padding"); |
372 | chunk_clear(&em); | |
373 | rng->destroy(rng); | |
374 | return FALSE; | |
c50ff68d AS |
375 | } |
376 | rng->destroy(rng); | |
377 | ||
828cefc3 MW |
378 | pos += padding; |
379 | ||
c50ff68d AS |
380 | /* append the padding terminator */ |
381 | *pos++ = 0x00; | |
382 | ||
383 | /* now add the data */ | |
384 | memcpy(pos, plain.ptr, plain.len); | |
8b0e0910 | 385 | DBG3(DBG_LIB, "padded data before rsa encryption: %B", &em); |
7daf5226 | 386 | |
d615ffdc | 387 | /* rsa encryption using PKCS#1 RSAEP */ |
c50ff68d | 388 | *crypto = rsaep(this, em); |
8b0e0910 | 389 | DBG3(DBG_LIB, "rsa encrypted data: %B", crypto); |
c50ff68d AS |
390 | chunk_clear(&em); |
391 | return TRUE; | |
552cc11b MW |
392 | } |
393 | ||
a944d209 | 394 | METHOD(public_key_t, get_keysize, int, |
876b61e1 | 395 | private_gmp_rsa_public_key_t *this) |
552cc11b | 396 | { |
a944d209 | 397 | return mpz_sizeinbase(this->n, 2); |
552cc11b MW |
398 | } |
399 | ||
876b61e1 MW |
400 | METHOD(public_key_t, get_encoding, bool, |
401 | private_gmp_rsa_public_key_t *this, cred_encoding_type_t type, | |
402 | chunk_t *encoding) | |
8b799d55 | 403 | { |
741680d1 | 404 | chunk_t n, e; |
dd04a68f | 405 | bool success; |
7daf5226 | 406 | |
741680d1 MW |
407 | n = gmp_mpz_to_chunk(this->n); |
408 | e = gmp_mpz_to_chunk(this->e); | |
7daf5226 MW |
409 | |
410 | success = lib->encoding->encode(lib->encoding, type, NULL, encoding, | |
da9724e6 | 411 | CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END); |
741680d1 MW |
412 | chunk_free(&n); |
413 | chunk_free(&e); | |
7daf5226 | 414 | |
741680d1 | 415 | return success; |
8b799d55 AS |
416 | } |
417 | ||
876b61e1 MW |
418 | METHOD(public_key_t, get_fingerprint, bool, |
419 | private_gmp_rsa_public_key_t *this, cred_encoding_type_t type, chunk_t *fp) | |
552cc11b | 420 | { |
741680d1 MW |
421 | chunk_t n, e; |
422 | bool success; | |
7daf5226 | 423 | |
741680d1 | 424 | if (lib->encoding->get_cache(lib->encoding, type, this, fp)) |
552cc11b | 425 | { |
741680d1 | 426 | return TRUE; |
552cc11b | 427 | } |
741680d1 MW |
428 | n = gmp_mpz_to_chunk(this->n); |
429 | e = gmp_mpz_to_chunk(this->e); | |
7daf5226 | 430 | |
741680d1 | 431 | success = lib->encoding->encode(lib->encoding, type, this, fp, |
da9724e6 | 432 | CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END); |
741680d1 MW |
433 | chunk_free(&n); |
434 | chunk_free(&e); | |
7daf5226 | 435 | |
741680d1 | 436 | return success; |
552cc11b MW |
437 | } |
438 | ||
876b61e1 MW |
439 | METHOD(public_key_t, get_ref, public_key_t*, |
440 | private_gmp_rsa_public_key_t *this) | |
552cc11b MW |
441 | { |
442 | ref_get(&this->ref); | |
876b61e1 | 443 | return &this->public.key; |
552cc11b MW |
444 | } |
445 | ||
876b61e1 MW |
446 | METHOD(public_key_t, destroy, void, |
447 | private_gmp_rsa_public_key_t *this) | |
552cc11b MW |
448 | { |
449 | if (ref_put(&this->ref)) | |
450 | { | |
451 | mpz_clear(this->n); | |
452 | mpz_clear(this->e); | |
741680d1 | 453 | lib->encoding->clear_cache(lib->encoding, this); |
552cc11b MW |
454 | free(this); |
455 | } | |
456 | } | |
457 | ||
458 | /** | |
1086d00e | 459 | * See header. |
552cc11b | 460 | */ |
1086d00e | 461 | gmp_rsa_public_key_t *gmp_rsa_public_key_load(key_type_t type, va_list args) |
552cc11b | 462 | { |
1086d00e MW |
463 | private_gmp_rsa_public_key_t *this; |
464 | chunk_t n, e; | |
465 | ||
466 | n = e = chunk_empty; | |
467 | while (TRUE) | |
468 | { | |
469 | switch (va_arg(args, builder_part_t)) | |
470 | { | |
471 | case BUILD_RSA_MODULUS: | |
472 | n = va_arg(args, chunk_t); | |
473 | continue; | |
474 | case BUILD_RSA_PUB_EXP: | |
475 | e = va_arg(args, chunk_t); | |
476 | continue; | |
477 | case BUILD_END: | |
478 | break; | |
479 | default: | |
480 | return NULL; | |
481 | } | |
482 | break; | |
483 | } | |
6681d98d | 484 | if (!e.len || !n.len || (n.ptr[n.len-1] & 0x01) == 0) |
1086d00e MW |
485 | { |
486 | return NULL; | |
487 | } | |
488 | ||
876b61e1 | 489 | INIT(this, |
ba31fe1f MW |
490 | .public = { |
491 | .key = { | |
492 | .get_type = _get_type, | |
493 | .verify = _verify, | |
494 | .encrypt = _encrypt_, | |
495 | .equals = public_key_equals, | |
496 | .get_keysize = _get_keysize, | |
497 | .get_fingerprint = _get_fingerprint, | |
498 | .has_fingerprint = public_key_has_fingerprint, | |
499 | .get_encoding = _get_encoding, | |
500 | .get_ref = _get_ref, | |
501 | .destroy = _destroy, | |
502 | }, | |
876b61e1 MW |
503 | }, |
504 | .ref = 1, | |
505 | ); | |
7daf5226 | 506 | |
8b799d55 AS |
507 | mpz_init(this->n); |
508 | mpz_init(this->e); | |
7daf5226 | 509 | |
7033a70f MW |
510 | mpz_import(this->n, n.len, 1, 1, 1, 0, n.ptr); |
511 | mpz_import(this->e, e.len, 1, 1, 1, 0, e.ptr); | |
7daf5226 | 512 | |
741680d1 | 513 | this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE; |
7daf5226 | 514 | |
6681d98d TB |
515 | if (!mpz_sgn(this->e)) |
516 | { | |
517 | destroy(this); | |
518 | return NULL; | |
519 | } | |
552cc11b MW |
520 | return &this->public; |
521 | } |