Codebase list libcryptx-perl / 5240e58
DSA params+key generation according FIPS-186-4 (part 1) Karel Miko 10 years ago
1 changed file(s) with 232 addition(s) and 98 deletion(s). Raw diff Collapse all Expand all
1717 #ifdef LTC_MDSA
1818
1919 /**
20 Create DSA parameters
21 @param prng An active PRNG state
22 @param wprng The index of the PRNG desired
23 @param group_size Size of the multiplicative group (octets)
24 @param modulus_size Size of the modulus (octets)
25 @param p [out] bignum where generated 'p' is stored (must be initialized by caller)
26 @param q [out] bignum where generated 'q' is stored (must be initialized by caller)
27 @param g [out] bignum where generated 'g' is stored (must be initialized by caller)
28 @return CRYPT_OK if successful, upon error this function will free all allocated memory
29 */
30 int dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g)
31 {
32 unsigned long L, N, n, outbytes, seedbytes, counter, j, i;
33 int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash;
34 unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE];
35 void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc;
36
37 /* check size */
38 if (group_size >= LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size) {
39 return CRYPT_INVALID_ARG;
40 }
41
42 /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
43 *
44 * L = The desired length of the prime p (in bits e.g. L = 1024)
45 * N = The desired length of the prime q (in bits e.g. N = 160)
46 * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N
47 * outlen = The bit length of Hash function
48 *
49 * 1. Check that the (L, N)
50 * 2. If (seedlen <N), then return INVALID.
51 * 3. n = ceil(L / outlen) - 1
52 * 4. b = L- 1 - (n * outlen)
53 * 5. domain_parameter_seed = an arbitrary sequence of seedlen bits
54 * 6. U = Hash (domain_parameter_seed) mod 2^(N-1)
55 * 7. q = 2^(N-1) + U + 1 - (U mod 2)
56 * 8. Test whether or not q is prime as specified in Appendix C.3
57 * 9. If qis not a prime, then go to step 5.
58 * 10. offset = 1
59 * 11. For counter = 0 to (4L- 1) do {
60 * For j=0 to n do {
61 * Vj = Hash ((domain_parameter_seed+ offset + j) mod 2^seedlen
62 * }
63 * W = V0 + (V1 *2^outlen) + ... + (Vn-1 * 2^((n-1) * outlen)) + ((Vn mod 2^b) * 2^(n * outlen))
64 * X = W + 2^(L-1) Comment: 0 <= W < 2^(L-1); hence 2^(L-1) <= X < 2^L
65 * c = X mod 2*q
66 * p = X - (c - 1) Comment: p ~ 1 (mod 2*q)
67 * If (p >= 2^(L-1)) {
68 * Test whether or not p is prime as specified in Appendix C.3.
69 * 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
70 * }
71 * offset = offset + n + 1 Comment: Increment offset
72 * }
73 */
74
75 seedbytes = group_size;
76 L = modulus_size * 8;
77 N = group_size * 8;
78
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
85 if (N <= 256) {
86 hash = register_hash(&sha256_desc);
87 }
88 else if (N <= 384) {
89 hash = register_hash(&sha384_desc);
90 }
91 else if (N <= 512) {
92 hash = register_hash(&sha512_desc);
93 }
94 else {
95 return CRYPT_INVALID_ARG; /* group_size too big */
96 }
97
98 if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; }
99 outbytes = hash_descriptor[hash].hashsize;
100
101 n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1;
102
103 if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; }
104 if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; }
105
106 err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, NULL);
107 if (err != CRYPT_OK) { goto cleanup1; };
108
109 if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; }
110 /* t2L1 = 2^(L-1) */
111 if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; }
112 /* t2N1 = 2^(N-1) */
113 if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; }
114 /* t2seedlen = 2^seedlen */
115
116 for(found_p=0; !found_p;) {
117 /* q */
118 for(found_q=0; !found_q;) {
119 if (prng_descriptor[wprng].read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; }
120 i = outbytes;
121 if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; }
122 if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; }
123 if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; }
124 if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; }
125 if (!mp_isodd(q)) mp_add_d(q, 1, q);
126 if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; } /* XXX-TODO rounds are ignored; no Lucas test */
127 if (res == LTC_MP_YES) found_q = 1;
128 }
129
130 /* p */
131 if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; }
132 /* printf("seed="); mp_fwrite(seedinc, 16, stdout); printf("\n"); //XXX-DEBUG */
133 if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; }
134 for(counter=0; counter < 4*L && !found_p; counter++) {
135 for(j=0; j<=n; j++) {
136 if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; }
137 if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; }
138 /* seedinc = (seedinc+1) % 2^seed_bitlen */
139 if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; }
140 zeromem(sbuf, seedbytes);
141 if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; }
142 i = outbytes;
143 err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i);
144 if (err != CRYPT_OK) { goto cleanup; }
145 }
146 if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; }
147 if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; }
148 if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; }
149 if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; }
150 if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; }
151 if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; }
152 if (mp_cmp(p, t2L1) != LTC_MP_LT) {
153 /* p >= 2^(L-1) */
154 if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; } /* XXX-TODO rounds are ignored; no Lucas test */
155 if (res == LTC_MP_YES) {
156 found_p = 1;
157 }
158 }
159 }
160 }
161
162 /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g
163 * 1. e = (p - 1)/q
164 * 2. h = any integer satisfying: 1 < h < (p - 1)
165 * h could be obtained from a random number generator or from a counter that changes after each use
166 * 3. g = h^e mod p
167 * 4. if (g == 1), then go to step 2.
168 *
169 */
170
171 if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; }
172 if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; }
173 /* e = (p - 1)/q */
174 i = mp_count_bits(p);
175 do {
176 do {
177 if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; }
178 } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT);
179 if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; }
180 /* h is randon and 1 < h < (p-1) */
181 if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; }
182 } while (mp_cmp_d(g, 1) == LTC_MP_EQ);
183
184 err = CRYPT_OK;
185 cleanup:
186 mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, NULL);
187 cleanup1:
188 XFREE(wbuf);
189 cleanup2:
190 XFREE(wbuf);
191 cleanup3:
192 return err;
193 }
194
195 /**
196 Create a DSA key (with given params)
197 @param prng An active PRNG state
198 @param wprng The index of the PRNG desired
199 @param group_size Size of the multiplicative group (octets)
200 @param modulus_size Size of the modulus (octets)
201 @param key [out] Where to store the created key
202 @param p_hex Hexadecimal string 'p'
203 @param q_hex Hexadecimal string 'q'
204 @param g_hex Hexadecimal string 'g'
205 @return CRYPT_OK if successful, upon error this function will free all allocated memory
206 */
207 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)
208 {
209 int err, qbits;
210
211 LTC_ARGCHK(key != NULL);
212
213 /* init mp_ints */
214 if ((err = mp_init_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) {
215 return err;
216 }
217
218 if (p_hex == NULL || q_hex == NULL || g_hex == NULL) {
219 /* generate params */
220 err = dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g);
221 if (err != CRYPT_OK) { goto cleanup; }
222 }
223 else {
224 /* read params */
225 if ((err = mp_read_radix(key->p, p_hex, 16)) != CRYPT_OK) { goto cleanup; }
226 if ((err = mp_read_radix(key->q, q_hex, 16)) != CRYPT_OK) { goto cleanup; }
227 if ((err = mp_read_radix(key->g, g_hex, 16)) != CRYPT_OK) { goto cleanup; }
228 /* XXX-TODO maybe do some validity check for p, q, g */
229 }
230
231 /* so now we have our DH structure, generator g, order q, modulus p
232 Now we need a random exponent [mod q] and it's power g^x mod p
233 */
234 qbits = mp_count_bits(key->q);
235 do {
236 if ((err = rand_bn_bits(key->x, qbits, prng, wprng)) != CRYPT_OK) { goto cleanup; }
237 /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */
238 } while (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT);
239 if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto cleanup; }
240 key->type = PK_PRIVATE;
241 key->qord = group_size;
242
243 return CRYPT_OK;
244
245 cleanup:
246 mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL);
247 return err;
248 }
249
250 /**
20251 Create a DSA key
21252 @param prng An active PRNG state
22253 @param wprng The index of the PRNG desired
27258 */
28259 int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
29260 {
30 void *tmp, *tmp2;
31 int err, res, qbits;
32 unsigned char *buf;
33
34 LTC_ARGCHK(key != NULL);
35 LTC_ARGCHK(ltc_mp.name != NULL);
36
37 /* check prng */
38 if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
39 return err;
40 }
41
42 /* check size */
43 if (group_size >= LTC_MDSA_MAX_GROUP || group_size <= 15 ||
44 group_size >= modulus_size || (modulus_size - group_size) >= LTC_MDSA_DELTA) {
45 return CRYPT_INVALID_ARG;
46 }
47
48 /* allocate ram */
49 buf = XMALLOC(LTC_MDSA_DELTA);
50 if (buf == NULL) {
51 return CRYPT_MEM;
52 }
53
54 /* init mp_ints */
55 if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) {
56 XFREE(buf);
57 return err;
58 }
59
60 /* make our prime q */
61 if ((err = rand_prime(key->q, group_size, prng, wprng)) != CRYPT_OK) { goto error; }
62
63 /* double q */
64 if ((err = mp_add(key->q, key->q, tmp)) != CRYPT_OK) { goto error; }
65
66 /* now make a random string and multply it against q */
67 if (prng_descriptor[wprng].read(buf, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) {
68 err = CRYPT_ERROR_READPRNG;
69 goto error;
70 }
71
72 /* force magnitude */
73 buf[0] |= 0xC0;
74
75 /* force even */
76 buf[modulus_size - group_size - 1] &= ~1;
77
78 if ((err = mp_read_unsigned_bin(tmp2, buf, modulus_size - group_size)) != CRYPT_OK) { goto error; }
79 if ((err = mp_mul(key->q, tmp2, key->p)) != CRYPT_OK) { goto error; }
80 if ((err = mp_add_d(key->p, 1, key->p)) != CRYPT_OK) { goto error; }
81
82 /* now loop until p is prime */
83 for (;;) {
84 if ((err = mp_prime_is_prime(key->p, 8, &res)) != CRYPT_OK) { goto error; }
85 if (res == LTC_MP_YES) break;
86
87 /* add 2q to p and 2 to tmp2 */
88 if ((err = mp_add(tmp, key->p, key->p)) != CRYPT_OK) { goto error; }
89 if ((err = mp_add_d(tmp2, 2, tmp2)) != CRYPT_OK) { goto error; }
90 }
91
92 /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */
93 mp_set(key->g, 1);
94
95 do {
96 if ((err = mp_add_d(key->g, 1, key->g)) != CRYPT_OK) { goto error; }
97 if ((err = mp_exptmod(key->g, tmp2, key->p, tmp)) != CRYPT_OK) { goto error; }
98 } while (mp_cmp_d(tmp, 1) == LTC_MP_EQ);
99
100 /* at this point tmp generates a group of order q mod p */
101 mp_exch(tmp, key->g);
102
103 /* so now we have our DH structure, generator g, order q, modulus p
104 Now we need a random exponent [mod q] and it's power g^x mod p
105 */
106 qbits = mp_count_bits(key->q);
107 do {
108 if ((err = rand_bn_bits(key->x, qbits, prng, wprng)) != CRYPT_OK) { goto error; }
109 /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */
110 } while (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT);
111 if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto error; }
112
113 key->type = PK_PRIVATE;
114 key->qord = group_size;
115
116 #ifdef LTC_CLEAN_STACK
117 zeromem(buf, LTC_MDSA_DELTA);
118 #endif
119
120 err = CRYPT_OK;
121 goto done;
122 error:
123 mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL);
124 done:
125 mp_clear_multi(tmp, tmp2, NULL);
126 XFREE(buf);
127 return err;
261 return dsa_make_key_ex(prng, wprng, group_size, modulus_size, key, NULL, NULL, NULL);
128262 }
129263
130264 #endif