LTC sync DSA new style
Karel Miko
6 years ago
46 | 46 | PPCODE: |
47 | 47 | { |
48 | 48 | int rv; |
49 | unsigned char pbin[512], qbin[512], gbin[512], xbin[512], ybin[512]; | |
50 | unsigned long plen=sizeof(pbin), qlen=sizeof(qbin), glen=sizeof(gbin), xlen=sizeof(xbin), ylen=sizeof(ybin); | |
51 | ||
49 | 52 | if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; } |
50 | rv = dsa_import_radix(16, p, q, g, x, y, &self->key); | |
51 | if (rv != CRYPT_OK) croak("FATAL: dsa_import_radix failed: %s", error_to_string(rv)); | |
53 | ||
54 | if (p && strlen(p) > 0 && q && strlen(q) > 0 && g && strlen(g) > 0 && y && strlen(y) > 0) { | |
55 | rv = radix_to_bin(p, 16, pbin, &plen); | |
56 | if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(p) failed: %s", error_to_string(rv)); | |
57 | rv = radix_to_bin(q, 16, qbin, &qlen); | |
58 | if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(q) failed: %s", error_to_string(rv)); | |
59 | rv = radix_to_bin(g, 16, gbin, &glen); | |
60 | if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(g) failed: %s", error_to_string(rv)); | |
61 | rv = dsa_set_pqg(pbin, plen, qbin, qlen, gbin, glen, &self->key); | |
62 | if (rv != CRYPT_OK) croak("FATAL: dsa_set_pqg failed: %s", error_to_string(rv)); | |
63 | ||
64 | rv = radix_to_bin(y, 16, ybin, &ylen); | |
65 | if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(y) failed: %s", error_to_string(rv)); | |
66 | if (x && strlen(x) > 0) { | |
67 | /* private */ | |
68 | rv = radix_to_bin(x, 16, xbin, &xlen); | |
69 | if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(x) failed: %s", error_to_string(rv)); | |
70 | rv = dsa_set_key(ybin, ylen, xbin, xlen, &self->key); | |
71 | if (rv != CRYPT_OK) croak("FATAL: dsa_set_key failed: %s", error_to_string(rv)); | |
72 | } | |
73 | else { | |
74 | /* public */ | |
75 | rv = dsa_set_key(ybin, ylen, NULL, 0, &self->key); | |
76 | if (rv != CRYPT_OK) croak("FATAL: dsa_set_key failed: %s", error_to_string(rv)); | |
77 | } | |
78 | } | |
79 | ||
52 | 80 | XPUSHs(ST(0)); /* return self */ |
53 | 81 | } |
54 | 82 |
61 | 61 | _import_hex(Crypt::PK::RSA self, char *N, char *e, char *d=NULL, char *p=NULL, char *q=NULL, char *dP=NULL, char *dQ=NULL, char *qP=NULL) |
62 | 62 | PPCODE: |
63 | 63 | { |
64 | int i, rv; | |
64 | int rv; | |
65 | 65 | unsigned char Nbin[1024], ebin[128], dbin[1024], pbin[512], qbin[512], dPbin[512], dQbin[512], qPbin[512]; |
66 | 66 | unsigned long Nlen=sizeof(Nbin), elen=sizeof(ebin), dlen=sizeof(dbin), plen=sizeof(pbin), |
67 | 67 | qlen=sizeof(qbin), dPlen=sizeof(dPbin), dQlen=sizeof(dQbin), qPlen=sizeof(qPbin); |
84 | 84 | ltc/pk/asn1/der/utctime/der_length_utctime.o ltc/pk/asn1/der/utf8/der_decode_utf8_string.o \ |
85 | 85 | ltc/pk/asn1/der/utf8/der_encode_utf8_string.o ltc/pk/asn1/der/utf8/der_length_utf8_string.o \ |
86 | 86 | ltc/pk/dh/dh.o ltc/pk/dh/dh_static.o ltc/pk/dh/dh_sys.o ltc/pk/dsa/dsa_decrypt_key.o \ |
87 | ltc/pk/dsa/dsa_encrypt_key.o ltc/pk/dsa/dsa_export.o ltc/pk/dsa/dsa_free.o ltc/pk/dsa/dsa_import.o \ | |
88 | ltc/pk/dsa/dsa_import_radix.o ltc/pk/dsa/dsa_make_key.o ltc/pk/dsa/dsa_shared_secret.o \ | |
89 | ltc/pk/dsa/dsa_sign_hash.o ltc/pk/dsa/dsa_verify_hash.o ltc/pk/dsa/dsa_verify_key.o \ | |
90 | ltc/pk/ecc/ecc.o ltc/pk/ecc/ecc_ansi_x963_export.o ltc/pk/ecc/ecc_ansi_x963_import.o \ | |
91 | ltc/pk/ecc/ecc_decrypt_key.o ltc/pk/ecc/ecc_dp_clear.o ltc/pk/ecc/ecc_dp_fill_from_sets.o \ | |
92 | ltc/pk/ecc/ecc_dp_from_oid.o ltc/pk/ecc/ecc_dp_from_params.o ltc/pk/ecc/ecc_dp_init.o \ | |
93 | ltc/pk/ecc/ecc_dp_set.o ltc/pk/ecc/ecc_encrypt_key.o ltc/pk/ecc/ecc_export.o ltc/pk/ecc/ecc_export_full.o \ | |
94 | ltc/pk/ecc/ecc_export_raw.o ltc/pk/ecc/ecc_free.o ltc/pk/ecc/ecc_get_size.o ltc/pk/ecc/ecc_import.o \ | |
95 | ltc/pk/ecc/ecc_import_full.o ltc/pk/ecc/ecc_import_pkcs8.o ltc/pk/ecc/ecc_import_raw.o \ | |
96 | ltc/pk/ecc/ecc_make_key.o ltc/pk/ecc/ecc_shared_secret.o ltc/pk/ecc/ecc_sign_hash.o \ | |
97 | ltc/pk/ecc/ecc_sizes.o ltc/pk/ecc/ecc_verify_hash.o ltc/pk/ecc/ecc_verify_key.o ltc/pk/ecc/ltc_ecc_export_point.o \ | |
98 | ltc/pk/ecc/ltc_ecc_import_point.o ltc/pk/ecc/ltc_ecc_is_point.o ltc/pk/ecc/ltc_ecc_is_point_at_infinity.o \ | |
99 | ltc/pk/ecc/ltc_ecc_is_valid_idx.o ltc/pk/ecc/ltc_ecc_map.o ltc/pk/ecc/ltc_ecc_mul2add.o \ | |
100 | ltc/pk/ecc/ltc_ecc_mulmod.o ltc/pk/ecc/ltc_ecc_mulmod_timing.o ltc/pk/ecc/ltc_ecc_points.o \ | |
101 | ltc/pk/ecc/ltc_ecc_projective_add_point.o ltc/pk/ecc/ltc_ecc_projective_dbl_point.o \ | |
87 | ltc/pk/dsa/dsa_encrypt_key.o ltc/pk/dsa/dsa_export.o ltc/pk/dsa/dsa_free.o ltc/pk/dsa/dsa_generate_key.o \ | |
88 | ltc/pk/dsa/dsa_generate_pqg.o ltc/pk/dsa/dsa_import.o ltc/pk/dsa/dsa_make_key.o ltc/pk/dsa/dsa_set.o \ | |
89 | ltc/pk/dsa/dsa_set_pqg_dsaparam.o ltc/pk/dsa/dsa_shared_secret.o ltc/pk/dsa/dsa_sign_hash.o \ | |
90 | ltc/pk/dsa/dsa_verify_hash.o ltc/pk/dsa/dsa_verify_key.o ltc/pk/ecc/ecc.o ltc/pk/ecc/ecc_ansi_x963_export.o \ | |
91 | ltc/pk/ecc/ecc_ansi_x963_import.o ltc/pk/ecc/ecc_decrypt_key.o ltc/pk/ecc/ecc_dp_clear.o \ | |
92 | ltc/pk/ecc/ecc_dp_fill_from_sets.o ltc/pk/ecc/ecc_dp_from_oid.o ltc/pk/ecc/ecc_dp_from_params.o \ | |
93 | ltc/pk/ecc/ecc_dp_init.o ltc/pk/ecc/ecc_dp_set.o ltc/pk/ecc/ecc_encrypt_key.o ltc/pk/ecc/ecc_export.o \ | |
94 | ltc/pk/ecc/ecc_export_full.o ltc/pk/ecc/ecc_export_raw.o ltc/pk/ecc/ecc_free.o ltc/pk/ecc/ecc_get_size.o \ | |
95 | ltc/pk/ecc/ecc_import.o ltc/pk/ecc/ecc_import_full.o ltc/pk/ecc/ecc_import_pkcs8.o \ | |
96 | ltc/pk/ecc/ecc_import_raw.o ltc/pk/ecc/ecc_make_key.o ltc/pk/ecc/ecc_shared_secret.o \ | |
97 | ltc/pk/ecc/ecc_sign_hash.o ltc/pk/ecc/ecc_sizes.o ltc/pk/ecc/ecc_verify_hash.o ltc/pk/ecc/ecc_verify_key.o \ | |
98 | ltc/pk/ecc/ltc_ecc_export_point.o ltc/pk/ecc/ltc_ecc_import_point.o ltc/pk/ecc/ltc_ecc_is_point.o \ | |
99 | ltc/pk/ecc/ltc_ecc_is_point_at_infinity.o ltc/pk/ecc/ltc_ecc_is_valid_idx.o ltc/pk/ecc/ltc_ecc_map.o \ | |
100 | ltc/pk/ecc/ltc_ecc_mul2add.o ltc/pk/ecc/ltc_ecc_mulmod.o ltc/pk/ecc/ltc_ecc_mulmod_timing.o \ | |
101 | ltc/pk/ecc/ltc_ecc_points.o ltc/pk/ecc/ltc_ecc_projective_add_point.o ltc/pk/ecc/ltc_ecc_projective_dbl_point.o \ | |
102 | 102 | ltc/pk/pkcs1/pkcs_1_i2osp.o ltc/pk/pkcs1/pkcs_1_mgf1.o ltc/pk/pkcs1/pkcs_1_oaep_decode.o \ |
103 | 103 | ltc/pk/pkcs1/pkcs_1_oaep_encode.o ltc/pk/pkcs1/pkcs_1_os2ip.o ltc/pk/pkcs1/pkcs_1_pss_decode.o \ |
104 | 104 | ltc/pk/pkcs1/pkcs_1_pss_encode.o ltc/pk/pkcs1/pkcs_1_v1_5_decode.o ltc/pk/pkcs1/pkcs_1_v1_5_encode.o \ |
91 | 91 | ltc/pk/asn1/der/utf8/der_encode_utf8_string.obj ltc/pk/asn1/der/utf8/der_length_utf8_string.obj \ |
92 | 92 | ltc/pk/dh/dh.obj ltc/pk/dh/dh_static.obj ltc/pk/dh/dh_sys.obj ltc/pk/dsa/dsa_decrypt_key.obj \ |
93 | 93 | ltc/pk/dsa/dsa_encrypt_key.obj ltc/pk/dsa/dsa_export.obj ltc/pk/dsa/dsa_free.obj \ |
94 | ltc/pk/dsa/dsa_import.obj ltc/pk/dsa/dsa_import_radix.obj ltc/pk/dsa/dsa_make_key.obj \ | |
94 | ltc/pk/dsa/dsa_generate_key.obj ltc/pk/dsa/dsa_generate_pqg.obj ltc/pk/dsa/dsa_import.obj \ | |
95 | ltc/pk/dsa/dsa_make_key.obj ltc/pk/dsa/dsa_set.obj ltc/pk/dsa/dsa_set_pqg_dsaparam.obj \ | |
95 | 96 | ltc/pk/dsa/dsa_shared_secret.obj ltc/pk/dsa/dsa_sign_hash.obj ltc/pk/dsa/dsa_verify_hash.obj \ |
96 | 97 | ltc/pk/dsa/dsa_verify_key.obj ltc/pk/ecc/ecc.obj ltc/pk/ecc/ecc_ansi_x963_export.obj \ |
97 | 98 | ltc/pk/ecc/ecc_ansi_x963_import.obj ltc/pk/ecc/ecc_decrypt_key.obj ltc/pk/ecc/ecc_dp_clear.obj \ |
471 | 471 | |
472 | 472 | int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); |
473 | 473 | |
474 | int dsa_make_key_ex(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key, char* p_hex, char* q_hex, char* g_hex); | |
475 | ||
476 | int dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g); | |
474 | int dsa_set_pqg(const unsigned char *p, unsigned long plen, | |
475 | const unsigned char *q, unsigned long qlen, | |
476 | const unsigned char *g, unsigned long glen, | |
477 | dsa_key *key); | |
478 | int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, dsa_key *key); | |
479 | int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); | |
480 | ||
481 | int dsa_set_key(const unsigned char *pub, unsigned long publen, | |
482 | const unsigned char *priv, unsigned long privlen, | |
483 | dsa_key *key); | |
484 | int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key); | |
477 | 485 | |
478 | 486 | void dsa_free(dsa_key *key); |
479 | 487 | |
502 | 510 | unsigned char *out, unsigned long *outlen, |
503 | 511 | dsa_key *key); |
504 | 512 | |
505 | int dsa_import_radix(int radix, char *p, char *q, char *g, char *x, char *y, dsa_key *key); | |
506 | 513 | int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key); |
507 | 514 | int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key); |
508 | 515 | int dsa_verify_key(dsa_key *key, int *stat); |
34 | 34 | unsigned char *expt, *skey; |
35 | 35 | void *g_pub, *g_priv; |
36 | 36 | unsigned long x, y; |
37 | int err, qbits; | |
37 | int err; | |
38 | 38 | |
39 | 39 | LTC_ARGCHK(in != NULL); |
40 | 40 | LTC_ARGCHK(out != NULL); |
72 | 72 | return CRYPT_MEM; |
73 | 73 | } |
74 | 74 | |
75 | /* make a random g_priv, g_pub = g^x pair */ | |
76 | qbits = mp_count_bits(key->q); | |
77 | do { | |
78 | if ((err = rand_bn_bits(g_priv, qbits, prng, wprng)) != CRYPT_OK) { | |
79 | goto LBL_ERR; | |
80 | } | |
81 | /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */ | |
82 | } while (mp_cmp_d(g_priv, 0) != LTC_MP_GT || mp_cmp(g_priv, key->q) != LTC_MP_LT); | |
75 | /* make a random g_priv, g_pub = g^x pair | |
76 | private key x should be in range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) | |
77 | */ | |
78 | if ((err = rand_bn_upto(g_priv, key->q, prng, wprng)) != CRYPT_OK) { | |
79 | goto LBL_ERR; | |
80 | } | |
83 | 81 | |
84 | 82 | /* compute y */ |
85 | 83 | if ((err = mp_exptmod(key->g, g_priv, key->p, g_pub)) != CRYPT_OK) { |
21 | 21 | void dsa_free(dsa_key *key) |
22 | 22 | { |
23 | 23 | LTC_ARGCHKVD(key != NULL); |
24 | mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL); | |
24 | mp_cleanup_multi(&key->y, &key->x, &key->q, &key->g, &key->p, NULL); | |
25 | key->type = key->qord = 0; | |
25 | 26 | } |
26 | 27 | |
27 | 28 | #endif |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | */ | |
8 | #include "tomcrypt.h" | |
9 | ||
10 | /** | |
11 | @file dsa_make_key.c | |
12 | DSA implementation, generate a DSA key | |
13 | */ | |
14 | ||
15 | #ifdef LTC_MDSA | |
16 | ||
17 | /** | |
18 | Create a DSA key | |
19 | @param prng An active PRNG state | |
20 | @param wprng The index of the PRNG desired | |
21 | @param key [in/out] Where to store the created key | |
22 | @return CRYPT_OK if successful. | |
23 | */ | |
24 | int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key) | |
25 | { | |
26 | int err; | |
27 | ||
28 | LTC_ARGCHK(key != NULL); | |
29 | LTC_ARGCHK(ltc_mp.name != NULL); | |
30 | ||
31 | /* so now we have our DH structure, generator g, order q, modulus p | |
32 | Now we need a random exponent [mod q] and it's power g^x mod p | |
33 | */ | |
34 | /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */ | |
35 | if ((err = rand_bn_upto(key->x, key->q, prng, wprng)) != CRYPT_OK) { return err; } | |
36 | if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { return err; } | |
37 | key->type = PK_PRIVATE; | |
38 | ||
39 | return CRYPT_OK; | |
40 | } | |
41 | ||
42 | #endif | |
43 | ||
44 | /* ref: $Format:%D$ */ | |
45 | /* git commit: $Format:%H$ */ | |
46 | /* commit time: $Format:%ai$ */ |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | */ | |
8 | #include "tomcrypt.h" | |
9 | ||
10 | /** | |
11 | @file dsa_generate_pqg.c | |
12 | DSA implementation - generate DSA parameters p, q & g | |
13 | */ | |
14 | ||
15 | #ifdef LTC_MDSA | |
16 | ||
17 | /** | |
18 | Create DSA parameters (INTERNAL ONLY, not part of public API) | |
19 | @param prng An active PRNG state | |
20 | @param wprng The index of the PRNG desired | |
21 | @param group_size Size of the multiplicative group (octets) | |
22 | @param modulus_size Size of the modulus (octets) | |
23 | @param p [out] bignum where generated 'p' is stored (must be initialized by caller) | |
24 | @param q [out] bignum where generated 'q' is stored (must be initialized by caller) | |
25 | @param g [out] bignum where generated 'g' is stored (must be initialized by caller) | |
26 | @return CRYPT_OK if successful, upon error this function will free all allocated memory | |
27 | */ | |
28 | static int _dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g) | |
29 | { | |
30 | unsigned long L, N, n, outbytes, seedbytes, counter, j, i; | |
31 | int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash; | |
32 | unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE]; | |
33 | void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc; | |
34 | ||
35 | /* check size */ | |
36 | if (group_size >= LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size) { | |
37 | return CRYPT_INVALID_ARG; | |
38 | } | |
39 | ||
40 | /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function | |
41 | * | |
42 | * L = The desired length of the prime p (in bits e.g. L = 1024) | |
43 | * N = The desired length of the prime q (in bits e.g. N = 160) | |
44 | * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N | |
45 | * outlen = The bit length of Hash function | |
46 | * | |
47 | * 1. Check that the (L, N) | |
48 | * 2. If (seedlen <N), then return INVALID. | |
49 | * 3. n = ceil(L / outlen) - 1 | |
50 | * 4. b = L- 1 - (n * outlen) | |
51 | * 5. domain_parameter_seed = an arbitrary sequence of seedlen bits | |
52 | * 6. U = Hash (domain_parameter_seed) mod 2^(N-1) | |
53 | * 7. q = 2^(N-1) + U + 1 - (U mod 2) | |
54 | * 8. Test whether or not q is prime as specified in Appendix C.3 | |
55 | * 9. If qis not a prime, then go to step 5. | |
56 | * 10. offset = 1 | |
57 | * 11. For counter = 0 to (4L- 1) do { | |
58 | * For j=0 to n do { | |
59 | * Vj = Hash ((domain_parameter_seed+ offset + j) mod 2^seedlen | |
60 | * } | |
61 | * W = V0 + (V1 *2^outlen) + ... + (Vn-1 * 2^((n-1) * outlen)) + ((Vn mod 2^b) * 2^(n * outlen)) | |
62 | * X = W + 2^(L-1) Comment: 0 <= W < 2^(L-1); hence 2^(L-1) <= X < 2^L | |
63 | * c = X mod 2*q | |
64 | * p = X - (c - 1) Comment: p ~ 1 (mod 2*q) | |
65 | * If (p >= 2^(L-1)) { | |
66 | * Test whether or not p is prime as specified in Appendix C.3. | |
67 | * If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter | |
68 | * } | |
69 | * offset = offset + n + 1 Comment: Increment offset | |
70 | * } | |
71 | */ | |
72 | ||
73 | seedbytes = group_size; | |
74 | L = modulus_size * 8; | |
75 | N = group_size * 8; | |
76 | ||
77 | /* XXX-TODO no Lucas test */ | |
78 | #ifdef LTC_MPI_HAS_LUCAS_TEST | |
79 | /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ | |
80 | mr_tests_p = (L <= 2048) ? 3 : 2; | |
81 | if (N <= 160) { mr_tests_q = 19; } | |
82 | else if (N <= 224) { mr_tests_q = 24; } | |
83 | else { mr_tests_q = 27; } | |
84 | #else | |
85 | /* M-R tests (without Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ | |
86 | if (L <= 1024) { mr_tests_p = 40; } | |
87 | else if (L <= 2048) { mr_tests_p = 56; } | |
88 | else { mr_tests_p = 64; } | |
89 | ||
90 | if (N <= 160) { mr_tests_q = 40; } | |
91 | else if (N <= 224) { mr_tests_q = 56; } | |
92 | else { mr_tests_q = 64; } | |
93 | #endif | |
94 | ||
95 | if (N <= 256) { | |
96 | hash = register_hash(&sha256_desc); | |
97 | } | |
98 | else if (N <= 384) { | |
99 | hash = register_hash(&sha384_desc); | |
100 | } | |
101 | else if (N <= 512) { | |
102 | hash = register_hash(&sha512_desc); | |
103 | } | |
104 | else { | |
105 | return CRYPT_INVALID_ARG; /* group_size too big */ | |
106 | } | |
107 | ||
108 | if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } | |
109 | outbytes = hash_descriptor[hash].hashsize; | |
110 | ||
111 | n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1; | |
112 | ||
113 | if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; } | |
114 | if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; } | |
115 | ||
116 | err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, NULL); | |
117 | if (err != CRYPT_OK) { goto cleanup1; } | |
118 | ||
119 | if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; } | |
120 | /* t2L1 = 2^(L-1) */ | |
121 | if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; } | |
122 | /* t2N1 = 2^(N-1) */ | |
123 | if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; } | |
124 | /* t2seedlen = 2^seedlen */ | |
125 | ||
126 | for(found_p=0; !found_p;) { | |
127 | /* q */ | |
128 | for(found_q=0; !found_q;) { | |
129 | if (prng_descriptor[wprng].read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; } | |
130 | i = outbytes; | |
131 | if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; } | |
132 | if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; } | |
133 | if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; } | |
134 | if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; } | |
135 | if (!mp_isodd(q)) mp_add_d(q, 1, q); | |
136 | if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; } | |
137 | if (res == LTC_MP_YES) found_q = 1; | |
138 | } | |
139 | ||
140 | /* p */ | |
141 | if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; } | |
142 | if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; } | |
143 | for(counter=0; counter < 4*L && !found_p; counter++) { | |
144 | for(j=0; j<=n; j++) { | |
145 | if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; } | |
146 | if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; } | |
147 | /* seedinc = (seedinc+1) % 2^seed_bitlen */ | |
148 | if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; } | |
149 | zeromem(sbuf, seedbytes); | |
150 | if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; } | |
151 | i = outbytes; | |
152 | err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i); | |
153 | if (err != CRYPT_OK) { goto cleanup; } | |
154 | } | |
155 | if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; } | |
156 | if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; } | |
157 | if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; } | |
158 | if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; } | |
159 | if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; } | |
160 | if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; } | |
161 | if (mp_cmp(p, t2L1) != LTC_MP_LT) { | |
162 | /* p >= 2^(L-1) */ | |
163 | if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; } | |
164 | if (res == LTC_MP_YES) { | |
165 | found_p = 1; | |
166 | } | |
167 | } | |
168 | } | |
169 | } | |
170 | ||
171 | /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g | |
172 | * 1. e = (p - 1)/q | |
173 | * 2. h = any integer satisfying: 1 < h < (p - 1) | |
174 | * h could be obtained from a random number generator or from a counter that changes after each use | |
175 | * 3. g = h^e mod p | |
176 | * 4. if (g == 1), then go to step 2. | |
177 | * | |
178 | */ | |
179 | ||
180 | if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; } | |
181 | if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; } | |
182 | /* e = (p - 1)/q */ | |
183 | i = mp_count_bits(p); | |
184 | do { | |
185 | do { | |
186 | if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; } | |
187 | } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT); | |
188 | if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; } | |
189 | /* h is randon and 1 < h < (p-1) */ | |
190 | if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; } | |
191 | } while (mp_cmp_d(g, 1) == LTC_MP_EQ); | |
192 | ||
193 | err = CRYPT_OK; | |
194 | cleanup: | |
195 | mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, NULL); | |
196 | cleanup1: | |
197 | XFREE(sbuf); | |
198 | cleanup2: | |
199 | XFREE(wbuf); | |
200 | cleanup3: | |
201 | return err; | |
202 | } | |
203 | ||
204 | /** | |
205 | Generate DSA parameters p, q & g | |
206 | @param prng An active PRNG state | |
207 | @param wprng The index of the PRNG desired | |
208 | @param group_size Size of the multiplicative group (octets) | |
209 | @param modulus_size Size of the modulus (octets) | |
210 | @param key [out] Where to store the created key | |
211 | @return CRYPT_OK if successful. | |
212 | */ | |
213 | int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) | |
214 | { | |
215 | int err; | |
216 | ||
217 | LTC_ARGCHK(key != NULL); | |
218 | LTC_ARGCHK(ltc_mp.name != NULL); | |
219 | ||
220 | /* init mp_ints */ | |
221 | if ((err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL)) != CRYPT_OK) { | |
222 | return err; | |
223 | } | |
224 | /* generate params */ | |
225 | err = _dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g); | |
226 | if (err != CRYPT_OK) { | |
227 | goto cleanup; | |
228 | } | |
229 | ||
230 | key->qord = group_size; | |
231 | ||
232 | return CRYPT_OK; | |
233 | ||
234 | cleanup: | |
235 | dsa_free(key); | |
236 | return err; | |
237 | } | |
238 | ||
239 | #endif | |
240 | ||
241 | /* ref: $Format:%D$ */ | |
242 | /* git commit: $Format:%H$ */ | |
243 | /* commit time: $Format:%ai$ */ |
124 | 124 | |
125 | 125 | return CRYPT_OK; |
126 | 126 | LBL_ERR: |
127 | mp_clear_multi(key->p, key->g, key->q, key->x, key->y, NULL); | |
127 | dsa_free(key); | |
128 | 128 | return err; |
129 | 129 | } |
130 | 130 |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | */ | |
8 | #include "tomcrypt.h" | |
9 | ||
10 | /** | |
11 | Import DSA public or private key from raw numbers | |
12 | @param radix the radix the numbers are represented in (2-64, 16 = hexadecimal) | |
13 | @param p DSA's p in radix representation | |
14 | @param q DSA's q in radix representation | |
15 | @param g DSA's g in radix representation | |
16 | @param x DSA's x in radix representation (only private key, NULL for public key) | |
17 | @param y DSA's y in radix representation | |
18 | @param key [out] the destination for the imported key | |
19 | @return CRYPT_OK if successful, upon error allocated memory is freed | |
20 | */ | |
21 | ||
22 | #ifdef LTC_MDSA | |
23 | ||
24 | int dsa_import_radix(int radix, char *p, char *q, char *g, char *x, char *y, dsa_key *key) | |
25 | { | |
26 | int err; | |
27 | ||
28 | LTC_ARGCHK(p != NULL); | |
29 | LTC_ARGCHK(q != NULL); | |
30 | LTC_ARGCHK(g != NULL); | |
31 | LTC_ARGCHK(y != NULL); | |
32 | LTC_ARGCHK(ltc_mp.name != NULL); | |
33 | ||
34 | /* init key */ | |
35 | err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL); | |
36 | if (err != CRYPT_OK) return err; | |
37 | ||
38 | if ((err = mp_read_radix(key->p , p , radix)) != CRYPT_OK) { goto LBL_ERR; } | |
39 | if ((err = mp_read_radix(key->q , q , radix)) != CRYPT_OK) { goto LBL_ERR; } | |
40 | if ((err = mp_read_radix(key->g , g , radix)) != CRYPT_OK) { goto LBL_ERR; } | |
41 | if ((err = mp_read_radix(key->y , y , radix)) != CRYPT_OK) { goto LBL_ERR; } | |
42 | if (x && strlen(x) > 0) { | |
43 | key->type = PK_PRIVATE; | |
44 | if ((err = mp_read_radix(key->x , x , radix)) != CRYPT_OK) { goto LBL_ERR; } | |
45 | } | |
46 | else { | |
47 | key->type = PK_PUBLIC; | |
48 | } | |
49 | ||
50 | key->qord = mp_unsigned_bin_size(key->q); | |
51 | ||
52 | if (key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 || | |
53 | (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) || (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA) { | |
54 | err = CRYPT_INVALID_PACKET; | |
55 | goto LBL_ERR; | |
56 | } | |
57 | return CRYPT_OK; | |
58 | ||
59 | LBL_ERR: | |
60 | mp_clear_multi(key->p, key->g, key->q, key->x, key->y, NULL); | |
61 | return err; | |
62 | } | |
63 | ||
64 | #endif |
9 | 9 | |
10 | 10 | /** |
11 | 11 | @file dsa_make_key.c |
12 | DSA implementation, generate a DSA key, Tom St Denis | |
12 | DSA implementation, generate a DSA key | |
13 | 13 | */ |
14 | 14 | |
15 | 15 | #ifdef LTC_MDSA |
16 | 16 | |
17 | 17 | /** |
18 | Create DSA parameters | |
19 | @param prng An active PRNG state | |
20 | @param wprng The index of the PRNG desired | |
21 | @param group_size Size of the multiplicative group (octets) | |
22 | @param modulus_size Size of the modulus (octets) | |
23 | @param p [out] bignum where generated 'p' is stored (must be initialized by caller) | |
24 | @param q [out] bignum where generated 'q' is stored (must be initialized by caller) | |
25 | @param g [out] bignum where generated 'g' is stored (must be initialized by caller) | |
26 | @return CRYPT_OK if successful, upon error this function will free all allocated memory | |
27 | */ | |
28 | int dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g) | |
29 | { | |
30 | unsigned long L, N, n, outbytes, seedbytes, counter, j, i; | |
31 | int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash; | |
32 | unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE]; | |
33 | void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc; | |
34 | ||
35 | /* check size */ | |
36 | if (group_size >= LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size) { | |
37 | return CRYPT_INVALID_ARG; | |
38 | } | |
39 | ||
40 | /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function | |
41 | * | |
42 | * L = The desired length of the prime p (in bits e.g. L = 1024) | |
43 | * N = The desired length of the prime q (in bits e.g. N = 160) | |
44 | * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N | |
45 | * outlen = The bit length of Hash function | |
46 | * | |
47 | * 1. Check that the (L, N) | |
48 | * 2. If (seedlen <N), then return INVALID. | |
49 | * 3. n = ceil(L / outlen) - 1 | |
50 | * 4. b = L- 1 - (n * outlen) | |
51 | * 5. domain_parameter_seed = an arbitrary sequence of seedlen bits | |
52 | * 6. U = Hash (domain_parameter_seed) mod 2^(N-1) | |
53 | * 7. q = 2^(N-1) + U + 1 - (U mod 2) | |
54 | * 8. Test whether or not q is prime as specified in Appendix C.3 | |
55 | * 9. If qis not a prime, then go to step 5. | |
56 | * 10. offset = 1 | |
57 | * 11. For counter = 0 to (4L- 1) do { | |
58 | * For j=0 to n do { | |
59 | * Vj = Hash ((domain_parameter_seed+ offset + j) mod 2^seedlen | |
60 | * } | |
61 | * W = V0 + (V1 *2^outlen) + ... + (Vn-1 * 2^((n-1) * outlen)) + ((Vn mod 2^b) * 2^(n * outlen)) | |
62 | * X = W + 2^(L-1) Comment: 0 <= W < 2^(L-1); hence 2^(L-1) <= X < 2^L | |
63 | * c = X mod 2*q | |
64 | * p = X - (c - 1) Comment: p ~ 1 (mod 2*q) | |
65 | * If (p >= 2^(L-1)) { | |
66 | * Test whether or not p is prime as specified in Appendix C.3. | |
67 | * If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter | |
68 | * } | |
69 | * offset = offset + n + 1 Comment: Increment offset | |
70 | * } | |
71 | */ | |
72 | ||
73 | seedbytes = group_size; | |
74 | L = modulus_size * 8; | |
75 | N = group_size * 8; | |
76 | ||
77 | /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ | |
78 | mr_tests_p = (L <= 2048) ? 3 : 2; | |
79 | if (N <= 160) { mr_tests_q = 19; } | |
80 | else if (N <= 224) { mr_tests_q = 24; } | |
81 | else { mr_tests_q = 27; } | |
82 | ||
83 | if (N <= 256) { | |
84 | hash = register_hash(&sha256_desc); | |
85 | } | |
86 | else if (N <= 384) { | |
87 | hash = register_hash(&sha384_desc); | |
88 | } | |
89 | else if (N <= 512) { | |
90 | hash = register_hash(&sha512_desc); | |
91 | } | |
92 | else { | |
93 | return CRYPT_INVALID_ARG; /* group_size too big */ | |
94 | } | |
95 | ||
96 | if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } | |
97 | outbytes = hash_descriptor[hash].hashsize; | |
98 | ||
99 | n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1; | |
100 | ||
101 | if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; } | |
102 | if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; } | |
103 | ||
104 | err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, NULL); | |
105 | if (err != CRYPT_OK) { goto cleanup1; } | |
106 | ||
107 | if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; } | |
108 | /* t2L1 = 2^(L-1) */ | |
109 | if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; } | |
110 | /* t2N1 = 2^(N-1) */ | |
111 | if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; } | |
112 | /* t2seedlen = 2^seedlen */ | |
113 | ||
114 | for(found_p=0; !found_p;) { | |
115 | /* q */ | |
116 | for(found_q=0; !found_q;) { | |
117 | if (prng_descriptor[wprng].read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; } | |
118 | i = outbytes; | |
119 | if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; } | |
120 | if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; } | |
121 | if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; } | |
122 | if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; } | |
123 | if (!mp_isodd(q)) mp_add_d(q, 1, q); | |
124 | if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; } /* XXX-TODO rounds are ignored; no Lucas test */ | |
125 | if (res == LTC_MP_YES) found_q = 1; | |
126 | } | |
127 | ||
128 | /* p */ | |
129 | if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; } | |
130 | if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; } | |
131 | for(counter=0; counter < 4*L && !found_p; counter++) { | |
132 | for(j=0; j<=n; j++) { | |
133 | if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; } | |
134 | if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; } | |
135 | /* seedinc = (seedinc+1) % 2^seed_bitlen */ | |
136 | if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; } | |
137 | zeromem(sbuf, seedbytes); | |
138 | if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; } | |
139 | i = outbytes; | |
140 | err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i); | |
141 | if (err != CRYPT_OK) { goto cleanup; } | |
142 | } | |
143 | if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; } | |
144 | if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; } | |
145 | if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; } | |
146 | if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; } | |
147 | if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; } | |
148 | if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; } | |
149 | if (mp_cmp(p, t2L1) != LTC_MP_LT) { | |
150 | /* p >= 2^(L-1) */ | |
151 | if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; } /* XXX-TODO rounds are ignored; no Lucas test */ | |
152 | if (res == LTC_MP_YES) { | |
153 | found_p = 1; | |
154 | } | |
155 | } | |
156 | } | |
157 | } | |
158 | ||
159 | /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g | |
160 | * 1. e = (p - 1)/q | |
161 | * 2. h = any integer satisfying: 1 < h < (p - 1) | |
162 | * h could be obtained from a random number generator or from a counter that changes after each use | |
163 | * 3. g = h^e mod p | |
164 | * 4. if (g == 1), then go to step 2. | |
165 | * | |
166 | */ | |
167 | ||
168 | if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; } | |
169 | if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; } | |
170 | /* e = (p - 1)/q */ | |
171 | i = mp_count_bits(p); | |
172 | do { | |
173 | do { | |
174 | if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; } | |
175 | } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT); | |
176 | if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; } | |
177 | /* h is randon and 1 < h < (p-1) */ | |
178 | if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; } | |
179 | } while (mp_cmp_d(g, 1) == LTC_MP_EQ); | |
180 | ||
181 | err = CRYPT_OK; | |
182 | cleanup: | |
183 | mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, NULL); | |
184 | cleanup1: | |
185 | XFREE(sbuf); | |
186 | cleanup2: | |
187 | XFREE(wbuf); | |
188 | cleanup3: | |
189 | return err; | |
190 | } | |
191 | ||
192 | /** | |
193 | Create a DSA key (with given params) | |
18 | Old-style creation of a DSA key | |
194 | 19 | @param prng An active PRNG state |
195 | 20 | @param wprng The index of the PRNG desired |
196 | 21 | @param group_size Size of the multiplicative group (octets) |
197 | 22 | @param modulus_size Size of the modulus (octets) |
198 | 23 | @param key [out] Where to store the created key |
199 | @param p_hex Hexadecimal string 'p' | |
200 | @param q_hex Hexadecimal string 'q' | |
201 | @param g_hex Hexadecimal string 'g' | |
202 | @return CRYPT_OK if successful, upon error this function will free all allocated memory | |
203 | */ | |
204 | int dsa_make_key_ex(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key, char* p_hex, char* q_hex, char* g_hex) | |
205 | { | |
206 | int err, qbits; | |
207 | ||
208 | LTC_ARGCHK(key != NULL); | |
209 | ||
210 | /* init mp_ints */ | |
211 | if ((err = mp_init_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) { | |
212 | return err; | |
213 | } | |
214 | ||
215 | if (p_hex == NULL || q_hex == NULL || g_hex == NULL) { | |
216 | /* generate params */ | |
217 | err = dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g); | |
218 | if (err != CRYPT_OK) { goto cleanup; } | |
219 | } | |
220 | else { | |
221 | /* read params */ | |
222 | if ((err = mp_read_radix(key->p, p_hex, 16)) != CRYPT_OK) { goto cleanup; } | |
223 | if ((err = mp_read_radix(key->q, q_hex, 16)) != CRYPT_OK) { goto cleanup; } | |
224 | if ((err = mp_read_radix(key->g, g_hex, 16)) != CRYPT_OK) { goto cleanup; } | |
225 | /* XXX-TODO maybe do some validity check for p, q, g */ | |
226 | } | |
227 | ||
228 | /* so now we have our DH structure, generator g, order q, modulus p | |
229 | Now we need a random exponent [mod q] and it's power g^x mod p | |
230 | */ | |
231 | qbits = mp_count_bits(key->q); | |
232 | do { | |
233 | if ((err = rand_bn_bits(key->x, qbits, prng, wprng)) != CRYPT_OK) { goto cleanup; } | |
234 | /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */ | |
235 | } while (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT); | |
236 | if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto cleanup; } | |
237 | key->type = PK_PRIVATE; | |
238 | key->qord = group_size; | |
239 | ||
240 | return CRYPT_OK; | |
241 | ||
242 | cleanup: | |
243 | mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL); | |
244 | return err; | |
245 | } | |
246 | ||
247 | /** | |
248 | Create a DSA key | |
249 | @param prng An active PRNG state | |
250 | @param wprng The index of the PRNG desired | |
251 | @param group_size Size of the multiplicative group (octets) | |
252 | @param modulus_size Size of the modulus (octets) | |
253 | @param key [out] Where to store the created key | |
254 | @return CRYPT_OK if successful, upon error this function will free all allocated memory | |
24 | @return CRYPT_OK if successful. | |
255 | 25 | */ |
256 | 26 | int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) |
257 | 27 | { |
258 | return dsa_make_key_ex(prng, wprng, group_size, modulus_size, key, NULL, NULL, NULL); | |
28 | int err; | |
29 | ||
30 | if ((err = dsa_generate_pqg(prng, wprng, group_size, modulus_size, key)) != CRYPT_OK) { return err; } | |
31 | if ((err = dsa_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } | |
32 | ||
33 | return CRYPT_OK; | |
259 | 34 | } |
260 | 35 | |
261 | 36 | #endif |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | */ | |
8 | #include "tomcrypt.h" | |
9 | ||
10 | ||
11 | #ifdef LTC_MDSA | |
12 | ||
13 | /** | |
14 | Import DSA's p, q & g from raw numbers | |
15 | @param p DSA's p in binary representation | |
16 | @param plen The length of p | |
17 | @param q DSA's q in binary representation | |
18 | @param qlen The length of q | |
19 | @param g DSA's g in binary representation | |
20 | @param glen The length of g | |
21 | @param key [out] the destination for the imported key | |
22 | @return CRYPT_OK if successful. | |
23 | */ | |
24 | int dsa_set_pqg(const unsigned char *p, unsigned long plen, | |
25 | const unsigned char *q, unsigned long qlen, | |
26 | const unsigned char *g, unsigned long glen, | |
27 | dsa_key *key) | |
28 | { | |
29 | int err; | |
30 | ||
31 | LTC_ARGCHK(p != NULL); | |
32 | LTC_ARGCHK(q != NULL); | |
33 | LTC_ARGCHK(g != NULL); | |
34 | LTC_ARGCHK(key != NULL); | |
35 | LTC_ARGCHK(ltc_mp.name != NULL); | |
36 | ||
37 | /* init key */ | |
38 | err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL); | |
39 | if (err != CRYPT_OK) return err; | |
40 | ||
41 | if ((err = mp_read_unsigned_bin(key->p, (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; } | |
42 | if ((err = mp_read_unsigned_bin(key->g, (unsigned char *)g , glen)) != CRYPT_OK) { goto LBL_ERR; } | |
43 | if ((err = mp_read_unsigned_bin(key->q, (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; } | |
44 | ||
45 | key->qord = mp_unsigned_bin_size(key->q); | |
46 | ||
47 | if (key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 || | |
48 | (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) || (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA) { | |
49 | err = CRYPT_INVALID_PACKET; | |
50 | goto LBL_ERR; | |
51 | } | |
52 | return CRYPT_OK; | |
53 | ||
54 | LBL_ERR: | |
55 | dsa_free(key); | |
56 | return err; | |
57 | } | |
58 | ||
59 | /** | |
60 | Import DSA public or private key from raw numbers | |
61 | @param pub DSA's y (public key) in binary representation | |
62 | @param publen The length of pub | |
63 | @param priv DSA's x (private key) in binary representation (can be NULL when importing public key) | |
64 | @param privlen The length of priv | |
65 | @param key [out] the destination for the imported key | |
66 | @return CRYPT_OK if successful. | |
67 | */ | |
68 | int dsa_set_key(const unsigned char *pub, unsigned long publen, | |
69 | const unsigned char *priv, unsigned long privlen, | |
70 | dsa_key *key) | |
71 | { | |
72 | int err; | |
73 | ||
74 | LTC_ARGCHK(key != NULL); | |
75 | LTC_ARGCHK(key->x != NULL); | |
76 | LTC_ARGCHK(key->y != NULL); | |
77 | LTC_ARGCHK(key->p != NULL); | |
78 | LTC_ARGCHK(key->g != NULL); | |
79 | LTC_ARGCHK(key->q != NULL); | |
80 | LTC_ARGCHK(ltc_mp.name != NULL); | |
81 | ||
82 | if ((err = mp_read_unsigned_bin(key->y, (unsigned char *)pub , publen)) != CRYPT_OK) { goto LBL_ERR; } | |
83 | if (priv != NULL) { | |
84 | key->type = PK_PRIVATE; | |
85 | if ((err = mp_read_unsigned_bin(key->x, (unsigned char *)priv , privlen)) != CRYPT_OK) { goto LBL_ERR; } | |
86 | } | |
87 | else { | |
88 | key->type = PK_PUBLIC; | |
89 | } | |
90 | ||
91 | return CRYPT_OK; | |
92 | ||
93 | LBL_ERR: | |
94 | dsa_free(key); | |
95 | return err; | |
96 | } | |
97 | ||
98 | #endif | |
99 | ||
100 | /* ref: $Format:%D$ */ | |
101 | /* git commit: $Format:%H$ */ | |
102 | /* commit time: $Format:%ai$ */ |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | */ | |
8 | #include "tomcrypt.h" | |
9 | ||
10 | ||
11 | #ifdef LTC_MDSA | |
12 | ||
13 | /** | |
14 | Import DSA's p, q & g from dsaparam | |
15 | ||
16 | dsaparam data: openssl dsaparam -outform DER -out dsaparam.der 2048 | |
17 | ||
18 | @param dsaparam The DSA param DER encoded data | |
19 | @param dsaparamlen The length of dhparam data | |
20 | @param key [out] the destination for the imported key | |
21 | @return CRYPT_OK if successful. | |
22 | */ | |
23 | int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, | |
24 | dsa_key *key) | |
25 | { | |
26 | int err; | |
27 | ||
28 | LTC_ARGCHK(dsaparam != NULL); | |
29 | LTC_ARGCHK(key != NULL); | |
30 | LTC_ARGCHK(ltc_mp.name != NULL); | |
31 | ||
32 | /* init key */ | |
33 | err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL); | |
34 | if (err != CRYPT_OK) return err; | |
35 | ||
36 | if ((err = der_decode_sequence_multi(dsaparam, dsaparamlen, | |
37 | LTC_ASN1_INTEGER, 1UL, key->p, | |
38 | LTC_ASN1_INTEGER, 1UL, key->q, | |
39 | LTC_ASN1_INTEGER, 1UL, key->g, | |
40 | LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { | |
41 | goto LBL_ERR; | |
42 | } | |
43 | ||
44 | key->qord = mp_unsigned_bin_size(key->q); | |
45 | ||
46 | if (key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 || | |
47 | (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) || (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA) { | |
48 | err = CRYPT_INVALID_PACKET; | |
49 | goto LBL_ERR; | |
50 | } | |
51 | return CRYPT_OK; | |
52 | ||
53 | LBL_ERR: | |
54 | dsa_free(key); | |
55 | return err; | |
56 | } | |
57 | ||
58 | #endif | |
59 | ||
60 | /* ref: $Format:%D$ */ | |
61 | /* git commit: $Format:%H$ */ | |
62 | /* commit time: $Format:%ai$ */ |