1*726fad2aSDina K Nimeh /*
2*726fad2aSDina K Nimeh * CDDL HEADER START
3*726fad2aSDina K Nimeh *
4*726fad2aSDina K Nimeh * The contents of this file are subject to the terms of the
5*726fad2aSDina K Nimeh * Common Development and Distribution License (the "License").
6*726fad2aSDina K Nimeh * You may not use this file except in compliance with the License.
7*726fad2aSDina K Nimeh *
8*726fad2aSDina K Nimeh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*726fad2aSDina K Nimeh * or http://www.opensolaris.org/os/licensing.
10*726fad2aSDina K Nimeh * See the License for the specific language governing permissions
11*726fad2aSDina K Nimeh * and limitations under the License.
12*726fad2aSDina K Nimeh *
13*726fad2aSDina K Nimeh * When distributing Covered Code, include this CDDL HEADER in each
14*726fad2aSDina K Nimeh * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*726fad2aSDina K Nimeh * If applicable, add the following below this CDDL HEADER, with the
16*726fad2aSDina K Nimeh * fields enclosed by brackets "[]" replaced with your own identifying
17*726fad2aSDina K Nimeh * information: Portions Copyright [yyyy] [name of copyright owner]
18*726fad2aSDina K Nimeh *
19*726fad2aSDina K Nimeh * CDDL HEADER END
20*726fad2aSDina K Nimeh */
21*726fad2aSDina K Nimeh
22*726fad2aSDina K Nimeh /*
23*726fad2aSDina K Nimeh * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24*726fad2aSDina K Nimeh */
25*726fad2aSDina K Nimeh
26*726fad2aSDina K Nimeh /*
27*726fad2aSDina K Nimeh * This file contains DSA helper routines common to
28*726fad2aSDina K Nimeh * the PKCS11 soft token code and the kernel DSA code.
29*726fad2aSDina K Nimeh */
30*726fad2aSDina K Nimeh
31*726fad2aSDina K Nimeh #include <sys/types.h>
32*726fad2aSDina K Nimeh #include <bignum.h>
33*726fad2aSDina K Nimeh
34*726fad2aSDina K Nimeh #ifdef _KERNEL
35*726fad2aSDina K Nimeh #include <sys/param.h>
36*726fad2aSDina K Nimeh #else
37*726fad2aSDina K Nimeh #include <strings.h>
38*726fad2aSDina K Nimeh #include <cryptoutil.h>
39*726fad2aSDina K Nimeh #endif
40*726fad2aSDina K Nimeh
41*726fad2aSDina K Nimeh #include <sys/crypto/common.h>
42*726fad2aSDina K Nimeh #include "dsa_impl.h"
43*726fad2aSDina K Nimeh
44*726fad2aSDina K Nimeh
45*726fad2aSDina K Nimeh static CK_RV
convert_rv(BIG_ERR_CODE err)46*726fad2aSDina K Nimeh convert_rv(BIG_ERR_CODE err)
47*726fad2aSDina K Nimeh {
48*726fad2aSDina K Nimeh switch (err) {
49*726fad2aSDina K Nimeh
50*726fad2aSDina K Nimeh case BIG_OK:
51*726fad2aSDina K Nimeh return (CKR_OK);
52*726fad2aSDina K Nimeh
53*726fad2aSDina K Nimeh case BIG_NO_MEM:
54*726fad2aSDina K Nimeh return (CKR_HOST_MEMORY);
55*726fad2aSDina K Nimeh
56*726fad2aSDina K Nimeh case BIG_NO_RANDOM:
57*726fad2aSDina K Nimeh return (CKR_DEVICE_ERROR);
58*726fad2aSDina K Nimeh
59*726fad2aSDina K Nimeh case BIG_INVALID_ARGS:
60*726fad2aSDina K Nimeh return (CKR_ARGUMENTS_BAD);
61*726fad2aSDina K Nimeh
62*726fad2aSDina K Nimeh case BIG_DIV_BY_0:
63*726fad2aSDina K Nimeh default:
64*726fad2aSDina K Nimeh return (CKR_GENERAL_ERROR);
65*726fad2aSDina K Nimeh }
66*726fad2aSDina K Nimeh }
67*726fad2aSDina K Nimeh
68*726fad2aSDina K Nimeh /* size is in bits */
69*726fad2aSDina K Nimeh static BIG_ERR_CODE
DSA_key_init(DSAkey * key,int size)70*726fad2aSDina K Nimeh DSA_key_init(DSAkey *key, int size)
71*726fad2aSDina K Nimeh {
72*726fad2aSDina K Nimeh BIG_ERR_CODE err = BIG_OK;
73*726fad2aSDina K Nimeh int len, len160;
74*726fad2aSDina K Nimeh
75*726fad2aSDina K Nimeh len = BITLEN2BIGNUMLEN(size);
76*726fad2aSDina K Nimeh len160 = BIG_CHUNKS_FOR_160BITS;
77*726fad2aSDina K Nimeh key->size = size;
78*726fad2aSDina K Nimeh if ((err = big_init(&(key->q), len160)) != BIG_OK)
79*726fad2aSDina K Nimeh return (err);
80*726fad2aSDina K Nimeh if ((err = big_init(&(key->p), len)) != BIG_OK)
81*726fad2aSDina K Nimeh goto ret1;
82*726fad2aSDina K Nimeh if ((err = big_init(&(key->g), len)) != BIG_OK)
83*726fad2aSDina K Nimeh goto ret2;
84*726fad2aSDina K Nimeh if ((err = big_init(&(key->x), len160)) != BIG_OK)
85*726fad2aSDina K Nimeh goto ret3;
86*726fad2aSDina K Nimeh if ((err = big_init(&(key->y), len)) != BIG_OK)
87*726fad2aSDina K Nimeh goto ret4;
88*726fad2aSDina K Nimeh if ((err = big_init(&(key->k), len160)) != BIG_OK)
89*726fad2aSDina K Nimeh goto ret5;
90*726fad2aSDina K Nimeh if ((err = big_init(&(key->r), len160)) != BIG_OK)
91*726fad2aSDina K Nimeh goto ret6;
92*726fad2aSDina K Nimeh if ((err = big_init(&(key->s), len160)) != BIG_OK)
93*726fad2aSDina K Nimeh goto ret7;
94*726fad2aSDina K Nimeh if ((err = big_init(&(key->v), len160)) != BIG_OK)
95*726fad2aSDina K Nimeh goto ret8;
96*726fad2aSDina K Nimeh
97*726fad2aSDina K Nimeh return (BIG_OK);
98*726fad2aSDina K Nimeh
99*726fad2aSDina K Nimeh ret8:
100*726fad2aSDina K Nimeh big_finish(&(key->s));
101*726fad2aSDina K Nimeh ret7:
102*726fad2aSDina K Nimeh big_finish(&(key->r));
103*726fad2aSDina K Nimeh ret6:
104*726fad2aSDina K Nimeh big_finish(&(key->k));
105*726fad2aSDina K Nimeh ret5:
106*726fad2aSDina K Nimeh big_finish(&(key->y));
107*726fad2aSDina K Nimeh ret4:
108*726fad2aSDina K Nimeh big_finish(&(key->x));
109*726fad2aSDina K Nimeh ret3:
110*726fad2aSDina K Nimeh big_finish(&(key->g));
111*726fad2aSDina K Nimeh ret2:
112*726fad2aSDina K Nimeh big_finish(&(key->p));
113*726fad2aSDina K Nimeh ret1:
114*726fad2aSDina K Nimeh big_finish(&(key->q));
115*726fad2aSDina K Nimeh return (err);
116*726fad2aSDina K Nimeh }
117*726fad2aSDina K Nimeh
118*726fad2aSDina K Nimeh static void
DSA_key_finish(DSAkey * key)119*726fad2aSDina K Nimeh DSA_key_finish(DSAkey *key)
120*726fad2aSDina K Nimeh {
121*726fad2aSDina K Nimeh
122*726fad2aSDina K Nimeh big_finish(&(key->v));
123*726fad2aSDina K Nimeh big_finish(&(key->s));
124*726fad2aSDina K Nimeh big_finish(&(key->r));
125*726fad2aSDina K Nimeh big_finish(&(key->k));
126*726fad2aSDina K Nimeh big_finish(&(key->y));
127*726fad2aSDina K Nimeh big_finish(&(key->x));
128*726fad2aSDina K Nimeh big_finish(&(key->g));
129*726fad2aSDina K Nimeh big_finish(&(key->p));
130*726fad2aSDina K Nimeh big_finish(&(key->q));
131*726fad2aSDina K Nimeh
132*726fad2aSDina K Nimeh }
133*726fad2aSDina K Nimeh
134*726fad2aSDina K Nimeh /*
135*726fad2aSDina K Nimeh * Generate DSA private x and public y from prime p, subprime q, and base g.
136*726fad2aSDina K Nimeh */
137*726fad2aSDina K Nimeh static CK_RV
generate_dsa_key(DSAkey * key,int (* rfunc)(void *,size_t))138*726fad2aSDina K Nimeh generate_dsa_key(DSAkey *key, int (*rfunc)(void *, size_t))
139*726fad2aSDina K Nimeh {
140*726fad2aSDina K Nimeh BIG_ERR_CODE err;
141*726fad2aSDina K Nimeh int (*rf)(void *, size_t);
142*726fad2aSDina K Nimeh
143*726fad2aSDina K Nimeh rf = rfunc;
144*726fad2aSDina K Nimeh if (rf == NULL) {
145*726fad2aSDina K Nimeh #ifdef _KERNEL
146*726fad2aSDina K Nimeh rf = random_get_pseudo_bytes;
147*726fad2aSDina K Nimeh #else
148*726fad2aSDina K Nimeh rf = pkcs11_get_urandom;
149*726fad2aSDina K Nimeh #endif
150*726fad2aSDina K Nimeh }
151*726fad2aSDina K Nimeh do {
152*726fad2aSDina K Nimeh if ((err = big_random(&(key->x), DSA_SUBPRIME_BITS, rf)) !=
153*726fad2aSDina K Nimeh BIG_OK) {
154*726fad2aSDina K Nimeh return (convert_rv(err));
155*726fad2aSDina K Nimeh }
156*726fad2aSDina K Nimeh } while (big_cmp_abs(&(key->x), &(key->q)) > 0);
157*726fad2aSDina K Nimeh
158*726fad2aSDina K Nimeh if ((err = big_modexp(&(key->y), &(key->g), (&key->x), (&key->p),
159*726fad2aSDina K Nimeh NULL)) != BIG_OK)
160*726fad2aSDina K Nimeh return (convert_rv(err));
161*726fad2aSDina K Nimeh
162*726fad2aSDina K Nimeh return (CKR_OK);
163*726fad2aSDina K Nimeh }
164*726fad2aSDina K Nimeh
165*726fad2aSDina K Nimeh CK_RV
dsa_genkey_pair(DSAbytekey * bkey)166*726fad2aSDina K Nimeh dsa_genkey_pair(DSAbytekey *bkey)
167*726fad2aSDina K Nimeh {
168*726fad2aSDina K Nimeh CK_RV rv = CKR_OK;
169*726fad2aSDina K Nimeh BIG_ERR_CODE brv;
170*726fad2aSDina K Nimeh DSAkey dsakey;
171*726fad2aSDina K Nimeh uint32_t prime_bytes;
172*726fad2aSDina K Nimeh uint32_t subprime_bytes;
173*726fad2aSDina K Nimeh
174*726fad2aSDina K Nimeh prime_bytes = CRYPTO_BITS2BYTES(bkey->prime_bits);
175*726fad2aSDina K Nimeh
176*726fad2aSDina K Nimeh if ((prime_bytes < MIN_DSA_KEY_LEN) ||
177*726fad2aSDina K Nimeh (prime_bytes > MAX_DSA_KEY_LEN)) {
178*726fad2aSDina K Nimeh return (CKR_ATTRIBUTE_VALUE_INVALID);
179*726fad2aSDina K Nimeh }
180*726fad2aSDina K Nimeh
181*726fad2aSDina K Nimeh /*
182*726fad2aSDina K Nimeh * There is no check here that prime_bits must be a multiple of 64,
183*726fad2aSDina K Nimeh * and thus that prime_bytes must be a multiple of 8.
184*726fad2aSDina K Nimeh */
185*726fad2aSDina K Nimeh
186*726fad2aSDina K Nimeh subprime_bytes = CRYPTO_BITS2BYTES(bkey->subprime_bits);
187*726fad2aSDina K Nimeh
188*726fad2aSDina K Nimeh if (subprime_bytes != DSA_SUBPRIME_BYTES) {
189*726fad2aSDina K Nimeh return (CKR_ATTRIBUTE_VALUE_INVALID);
190*726fad2aSDina K Nimeh }
191*726fad2aSDina K Nimeh
192*726fad2aSDina K Nimeh if (bkey->public_y == NULL || bkey->private_x == NULL) {
193*726fad2aSDina K Nimeh return (CKR_ARGUMENTS_BAD);
194*726fad2aSDina K Nimeh }
195*726fad2aSDina K Nimeh
196*726fad2aSDina K Nimeh /*
197*726fad2aSDina K Nimeh * Initialize the DSA key.
198*726fad2aSDina K Nimeh * Note: big_extend takes length in words.
199*726fad2aSDina K Nimeh */
200*726fad2aSDina K Nimeh if ((brv = DSA_key_init(&dsakey, bkey->prime_bits)) != BIG_OK) {
201*726fad2aSDina K Nimeh rv = convert_rv(brv);
202*726fad2aSDina K Nimeh goto cleanexit;
203*726fad2aSDina K Nimeh }
204*726fad2aSDina K Nimeh
205*726fad2aSDina K Nimeh /* Convert prime p to bignum. */
206*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.p),
207*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(prime_bytes))) != BIG_OK) {
208*726fad2aSDina K Nimeh rv = convert_rv(brv);
209*726fad2aSDina K Nimeh goto cleanexit;
210*726fad2aSDina K Nimeh }
211*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.p), bkey->prime, prime_bytes);
212*726fad2aSDina K Nimeh
213*726fad2aSDina K Nimeh /* Convert prime q to bignum. */
214*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.q),
215*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(subprime_bytes))) != BIG_OK) {
216*726fad2aSDina K Nimeh rv = convert_rv(brv);
217*726fad2aSDina K Nimeh goto cleanexit;
218*726fad2aSDina K Nimeh }
219*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.q), bkey->subprime, subprime_bytes);
220*726fad2aSDina K Nimeh
221*726fad2aSDina K Nimeh /* Convert base g to bignum. */
222*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.g),
223*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(bkey->base_bytes))) != BIG_OK) {
224*726fad2aSDina K Nimeh rv = convert_rv(brv);
225*726fad2aSDina K Nimeh goto cleanexit;
226*726fad2aSDina K Nimeh }
227*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.g), bkey->base, bkey->base_bytes);
228*726fad2aSDina K Nimeh
229*726fad2aSDina K Nimeh /*
230*726fad2aSDina K Nimeh * Generate DSA key pair.
231*726fad2aSDina K Nimeh * Note: bignum.len is length of value in words.
232*726fad2aSDina K Nimeh */
233*726fad2aSDina K Nimeh if ((rv = generate_dsa_key(&dsakey, bkey->rfunc)) !=
234*726fad2aSDina K Nimeh CKR_OK) {
235*726fad2aSDina K Nimeh goto cleanexit;
236*726fad2aSDina K Nimeh }
237*726fad2aSDina K Nimeh
238*726fad2aSDina K Nimeh bkey->public_y_bits = CRYPTO_BYTES2BITS(prime_bytes);
239*726fad2aSDina K Nimeh bignum2bytestring(bkey->public_y, &(dsakey.y), prime_bytes);
240*726fad2aSDina K Nimeh
241*726fad2aSDina K Nimeh bkey->private_x_bits = CRYPTO_BYTES2BITS(DSA_SUBPRIME_BYTES);
242*726fad2aSDina K Nimeh bignum2bytestring(bkey->private_x, &(dsakey.x), DSA_SUBPRIME_BYTES);
243*726fad2aSDina K Nimeh
244*726fad2aSDina K Nimeh cleanexit:
245*726fad2aSDina K Nimeh DSA_key_finish(&dsakey);
246*726fad2aSDina K Nimeh
247*726fad2aSDina K Nimeh return (rv);
248*726fad2aSDina K Nimeh }
249*726fad2aSDina K Nimeh
250*726fad2aSDina K Nimeh /*
251*726fad2aSDina K Nimeh * DSA sign operation
252*726fad2aSDina K Nimeh */
253*726fad2aSDina K Nimeh CK_RV
dsa_sign(DSAbytekey * bkey,uchar_t * in,uint32_t inlen,uchar_t * out)254*726fad2aSDina K Nimeh dsa_sign(DSAbytekey *bkey, uchar_t *in, uint32_t inlen, uchar_t *out)
255*726fad2aSDina K Nimeh {
256*726fad2aSDina K Nimeh CK_RV rv = CKR_OK;
257*726fad2aSDina K Nimeh BIG_ERR_CODE brv;
258*726fad2aSDina K Nimeh DSAkey dsakey;
259*726fad2aSDina K Nimeh BIGNUM msg, tmp, tmp1;
260*726fad2aSDina K Nimeh uint32_t prime_bytes;
261*726fad2aSDina K Nimeh uint32_t subprime_bytes;
262*726fad2aSDina K Nimeh uint32_t value_bytes;
263*726fad2aSDina K Nimeh int (*rf)(void *, size_t);
264*726fad2aSDina K Nimeh
265*726fad2aSDina K Nimeh prime_bytes = CRYPTO_BITS2BYTES(bkey->prime_bits);
266*726fad2aSDina K Nimeh subprime_bytes = CRYPTO_BITS2BYTES(bkey->subprime_bits);
267*726fad2aSDina K Nimeh
268*726fad2aSDina K Nimeh if (DSA_SUBPRIME_BYTES != subprime_bytes) {
269*726fad2aSDina K Nimeh return (CKR_KEY_SIZE_RANGE);
270*726fad2aSDina K Nimeh }
271*726fad2aSDina K Nimeh
272*726fad2aSDina K Nimeh value_bytes = CRYPTO_BITS2BYTES(bkey->private_x_bits); /* len of x */
273*726fad2aSDina K Nimeh
274*726fad2aSDina K Nimeh if (DSA_SUBPRIME_BYTES < value_bytes) {
275*726fad2aSDina K Nimeh return (CKR_KEY_SIZE_RANGE);
276*726fad2aSDina K Nimeh }
277*726fad2aSDina K Nimeh
278*726fad2aSDina K Nimeh /*
279*726fad2aSDina K Nimeh * Initialize the DH key.
280*726fad2aSDina K Nimeh * Note: big_extend takes length in words.
281*726fad2aSDina K Nimeh */
282*726fad2aSDina K Nimeh if ((brv = DSA_key_init(&dsakey, bkey->prime_bits)) != BIG_OK) {
283*726fad2aSDina K Nimeh return (CKR_HOST_MEMORY);
284*726fad2aSDina K Nimeh }
285*726fad2aSDina K Nimeh
286*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.p),
287*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(prime_bytes))) != BIG_OK) {
288*726fad2aSDina K Nimeh rv = convert_rv(brv);
289*726fad2aSDina K Nimeh goto clean1;
290*726fad2aSDina K Nimeh }
291*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.p), bkey->prime, prime_bytes);
292*726fad2aSDina K Nimeh
293*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.q),
294*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(subprime_bytes))) != BIG_OK) {
295*726fad2aSDina K Nimeh rv = convert_rv(brv);
296*726fad2aSDina K Nimeh goto clean1;
297*726fad2aSDina K Nimeh }
298*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.q), bkey->subprime, subprime_bytes);
299*726fad2aSDina K Nimeh
300*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.g),
301*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(bkey->base_bytes))) != BIG_OK) {
302*726fad2aSDina K Nimeh rv = convert_rv(brv);
303*726fad2aSDina K Nimeh goto clean1;
304*726fad2aSDina K Nimeh }
305*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.g), bkey->base, bkey->base_bytes);
306*726fad2aSDina K Nimeh
307*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.x),
308*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(value_bytes))) != BIG_OK) {
309*726fad2aSDina K Nimeh rv = convert_rv(brv);
310*726fad2aSDina K Nimeh goto clean1;
311*726fad2aSDina K Nimeh }
312*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.x), bkey->private_x, value_bytes);
313*726fad2aSDina K Nimeh
314*726fad2aSDina K Nimeh if ((brv = big_init(&msg, BIG_CHUNKS_FOR_160BITS)) != BIG_OK) {
315*726fad2aSDina K Nimeh rv = convert_rv(brv);
316*726fad2aSDina K Nimeh goto clean1;
317*726fad2aSDina K Nimeh }
318*726fad2aSDina K Nimeh bytestring2bignum(&msg, in, inlen);
319*726fad2aSDina K Nimeh
320*726fad2aSDina K Nimeh /*
321*726fad2aSDina K Nimeh * Compute signature.
322*726fad2aSDina K Nimeh */
323*726fad2aSDina K Nimeh if ((brv = big_init(&tmp, CHARLEN2BIGNUMLEN(prime_bytes) +
324*726fad2aSDina K Nimeh 2 * BIG_CHUNKS_FOR_160BITS + 1)) != BIG_OK) {
325*726fad2aSDina K Nimeh rv = convert_rv(brv);
326*726fad2aSDina K Nimeh goto clean2;
327*726fad2aSDina K Nimeh }
328*726fad2aSDina K Nimeh if ((brv = big_init(&tmp1, 2 * BIG_CHUNKS_FOR_160BITS + 1)) != BIG_OK) {
329*726fad2aSDina K Nimeh rv = convert_rv(brv);
330*726fad2aSDina K Nimeh goto clean3;
331*726fad2aSDina K Nimeh }
332*726fad2aSDina K Nimeh
333*726fad2aSDina K Nimeh rf = bkey->rfunc;
334*726fad2aSDina K Nimeh if (rf == NULL) {
335*726fad2aSDina K Nimeh #ifdef _KERNEL
336*726fad2aSDina K Nimeh rf = random_get_pseudo_bytes;
337*726fad2aSDina K Nimeh #else
338*726fad2aSDina K Nimeh rf = pkcs11_get_urandom;
339*726fad2aSDina K Nimeh #endif
340*726fad2aSDina K Nimeh }
341*726fad2aSDina K Nimeh if ((brv = big_random(&(dsakey.k), DSA_SUBPRIME_BITS, rf)) != BIG_OK) {
342*726fad2aSDina K Nimeh rv = convert_rv(brv);
343*726fad2aSDina K Nimeh goto clean4;
344*726fad2aSDina K Nimeh }
345*726fad2aSDina K Nimeh
346*726fad2aSDina K Nimeh if ((brv = big_div_pos(NULL, &(dsakey.k), &(dsakey.k),
347*726fad2aSDina K Nimeh &(dsakey.q))) != BIG_OK) {
348*726fad2aSDina K Nimeh rv = convert_rv(brv);
349*726fad2aSDina K Nimeh goto clean4;
350*726fad2aSDina K Nimeh }
351*726fad2aSDina K Nimeh
352*726fad2aSDina K Nimeh if ((brv = big_modexp(&tmp, &(dsakey.g), &(dsakey.k), &(dsakey.p),
353*726fad2aSDina K Nimeh NULL)) != BIG_OK) {
354*726fad2aSDina K Nimeh rv = convert_rv(brv);
355*726fad2aSDina K Nimeh goto clean4;
356*726fad2aSDina K Nimeh }
357*726fad2aSDina K Nimeh
358*726fad2aSDina K Nimeh if ((brv = big_div_pos(NULL, &(dsakey.r), &tmp, &(dsakey.q))) !=
359*726fad2aSDina K Nimeh BIG_OK) {
360*726fad2aSDina K Nimeh rv = convert_rv(brv);
361*726fad2aSDina K Nimeh goto clean4;
362*726fad2aSDina K Nimeh }
363*726fad2aSDina K Nimeh
364*726fad2aSDina K Nimeh
365*726fad2aSDina K Nimeh if ((brv = big_ext_gcd_pos(NULL, NULL, &tmp, &(dsakey.q),
366*726fad2aSDina K Nimeh &(dsakey.k))) != BIG_OK) {
367*726fad2aSDina K Nimeh rv = convert_rv(brv);
368*726fad2aSDina K Nimeh goto clean4;
369*726fad2aSDina K Nimeh }
370*726fad2aSDina K Nimeh
371*726fad2aSDina K Nimeh if (tmp.sign == -1)
372*726fad2aSDina K Nimeh if ((brv = big_add(&tmp, &tmp, &(dsakey.q))) != BIG_OK) {
373*726fad2aSDina K Nimeh rv = convert_rv(brv);
374*726fad2aSDina K Nimeh goto clean4; /* tmp <- k^-1 */
375*726fad2aSDina K Nimeh }
376*726fad2aSDina K Nimeh
377*726fad2aSDina K Nimeh if ((brv = big_mul(&tmp1, &(dsakey.x), &(dsakey.r))) != BIG_OK) {
378*726fad2aSDina K Nimeh rv = convert_rv(brv);
379*726fad2aSDina K Nimeh goto clean4;
380*726fad2aSDina K Nimeh }
381*726fad2aSDina K Nimeh
382*726fad2aSDina K Nimeh if ((brv = big_add(&tmp1, &tmp1, &msg)) != BIG_OK) {
383*726fad2aSDina K Nimeh rv = convert_rv(brv);
384*726fad2aSDina K Nimeh goto clean4;
385*726fad2aSDina K Nimeh }
386*726fad2aSDina K Nimeh
387*726fad2aSDina K Nimeh if ((brv = big_mul(&tmp, &tmp1, &tmp)) != BIG_OK) {
388*726fad2aSDina K Nimeh rv = convert_rv(brv);
389*726fad2aSDina K Nimeh goto clean4;
390*726fad2aSDina K Nimeh }
391*726fad2aSDina K Nimeh
392*726fad2aSDina K Nimeh if ((brv = big_div_pos(NULL, &(dsakey.s), &tmp, &(dsakey.q))) !=
393*726fad2aSDina K Nimeh BIG_OK) {
394*726fad2aSDina K Nimeh rv = convert_rv(brv);
395*726fad2aSDina K Nimeh goto clean4;
396*726fad2aSDina K Nimeh }
397*726fad2aSDina K Nimeh
398*726fad2aSDina K Nimeh /*
399*726fad2aSDina K Nimeh * Signature is in DSA key r and s values, copy to out
400*726fad2aSDina K Nimeh */
401*726fad2aSDina K Nimeh bignum2bytestring(out, &(dsakey.r), DSA_SUBPRIME_BYTES);
402*726fad2aSDina K Nimeh bignum2bytestring(out + DSA_SUBPRIME_BYTES, &(dsakey.s),
403*726fad2aSDina K Nimeh DSA_SUBPRIME_BYTES);
404*726fad2aSDina K Nimeh
405*726fad2aSDina K Nimeh clean4:
406*726fad2aSDina K Nimeh big_finish(&tmp1);
407*726fad2aSDina K Nimeh clean3:
408*726fad2aSDina K Nimeh big_finish(&tmp);
409*726fad2aSDina K Nimeh clean2:
410*726fad2aSDina K Nimeh big_finish(&msg);
411*726fad2aSDina K Nimeh clean1:
412*726fad2aSDina K Nimeh DSA_key_finish(&dsakey);
413*726fad2aSDina K Nimeh
414*726fad2aSDina K Nimeh return (rv);
415*726fad2aSDina K Nimeh }
416*726fad2aSDina K Nimeh
417*726fad2aSDina K Nimeh /*
418*726fad2aSDina K Nimeh * DSA verify operation
419*726fad2aSDina K Nimeh */
420*726fad2aSDina K Nimeh CK_RV
dsa_verify(DSAbytekey * bkey,uchar_t * data,uchar_t * sig)421*726fad2aSDina K Nimeh dsa_verify(DSAbytekey *bkey, uchar_t *data, uchar_t *sig)
422*726fad2aSDina K Nimeh {
423*726fad2aSDina K Nimeh CK_RV rv = CKR_OK;
424*726fad2aSDina K Nimeh BIG_ERR_CODE brv;
425*726fad2aSDina K Nimeh DSAkey dsakey;
426*726fad2aSDina K Nimeh BIGNUM msg, tmp1, tmp2, tmp3;
427*726fad2aSDina K Nimeh uint32_t prime_bytes;
428*726fad2aSDina K Nimeh uint32_t subprime_bytes;
429*726fad2aSDina K Nimeh uint32_t value_bytes;
430*726fad2aSDina K Nimeh
431*726fad2aSDina K Nimeh prime_bytes = CRYPTO_BITS2BYTES(bkey->prime_bits);
432*726fad2aSDina K Nimeh subprime_bytes = CRYPTO_BITS2BYTES(bkey->subprime_bits);
433*726fad2aSDina K Nimeh
434*726fad2aSDina K Nimeh if (DSA_SUBPRIME_BYTES != subprime_bytes) {
435*726fad2aSDina K Nimeh return (CKR_KEY_SIZE_RANGE);
436*726fad2aSDina K Nimeh }
437*726fad2aSDina K Nimeh
438*726fad2aSDina K Nimeh if (prime_bytes < bkey->base_bytes) {
439*726fad2aSDina K Nimeh return (CKR_KEY_SIZE_RANGE);
440*726fad2aSDina K Nimeh }
441*726fad2aSDina K Nimeh
442*726fad2aSDina K Nimeh value_bytes = CRYPTO_BITS2BYTES(bkey->public_y_bits); /* len of y */
443*726fad2aSDina K Nimeh if (prime_bytes < value_bytes) {
444*726fad2aSDina K Nimeh return (CKR_KEY_SIZE_RANGE);
445*726fad2aSDina K Nimeh }
446*726fad2aSDina K Nimeh
447*726fad2aSDina K Nimeh /*
448*726fad2aSDina K Nimeh * Initialize the DSA key.
449*726fad2aSDina K Nimeh * Note: big_extend takes length in words.
450*726fad2aSDina K Nimeh */
451*726fad2aSDina K Nimeh if (DSA_key_init(&dsakey, bkey->prime_bits) != BIG_OK) {
452*726fad2aSDina K Nimeh return (CKR_HOST_MEMORY);
453*726fad2aSDina K Nimeh }
454*726fad2aSDina K Nimeh
455*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.p),
456*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(prime_bytes))) != BIG_OK) {
457*726fad2aSDina K Nimeh rv = convert_rv(brv);
458*726fad2aSDina K Nimeh goto clean1;
459*726fad2aSDina K Nimeh }
460*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.p), bkey->prime, prime_bytes);
461*726fad2aSDina K Nimeh
462*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.q),
463*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(subprime_bytes))) != BIG_OK) {
464*726fad2aSDina K Nimeh rv = convert_rv(brv);
465*726fad2aSDina K Nimeh goto clean1;
466*726fad2aSDina K Nimeh }
467*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.q), bkey->subprime, subprime_bytes);
468*726fad2aSDina K Nimeh
469*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.g),
470*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(bkey->base_bytes))) != BIG_OK) {
471*726fad2aSDina K Nimeh rv = convert_rv(brv);
472*726fad2aSDina K Nimeh goto clean1;
473*726fad2aSDina K Nimeh }
474*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.g), bkey->base, bkey->base_bytes);
475*726fad2aSDina K Nimeh
476*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.y),
477*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(value_bytes))) != BIG_OK) {
478*726fad2aSDina K Nimeh rv = convert_rv(brv);
479*726fad2aSDina K Nimeh goto clean1;
480*726fad2aSDina K Nimeh }
481*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.y), bkey->public_y, value_bytes);
482*726fad2aSDina K Nimeh
483*726fad2aSDina K Nimeh /*
484*726fad2aSDina K Nimeh * Copy signature to DSA key r and s values
485*726fad2aSDina K Nimeh */
486*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.r),
487*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(DSA_SUBPRIME_BYTES))) != BIG_OK) {
488*726fad2aSDina K Nimeh rv = convert_rv(brv);
489*726fad2aSDina K Nimeh goto clean1;
490*726fad2aSDina K Nimeh }
491*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.r), sig, DSA_SUBPRIME_BYTES);
492*726fad2aSDina K Nimeh
493*726fad2aSDina K Nimeh if ((brv = big_extend(&(dsakey.s),
494*726fad2aSDina K Nimeh CHARLEN2BIGNUMLEN(DSA_SUBPRIME_BYTES))) != BIG_OK) {
495*726fad2aSDina K Nimeh rv = convert_rv(brv);
496*726fad2aSDina K Nimeh goto clean1;
497*726fad2aSDina K Nimeh }
498*726fad2aSDina K Nimeh bytestring2bignum(&(dsakey.s), sig + DSA_SUBPRIME_BYTES,
499*726fad2aSDina K Nimeh DSA_SUBPRIME_BYTES);
500*726fad2aSDina K Nimeh
501*726fad2aSDina K Nimeh
502*726fad2aSDina K Nimeh if (big_init(&msg, BIG_CHUNKS_FOR_160BITS) != BIG_OK) {
503*726fad2aSDina K Nimeh rv = CKR_HOST_MEMORY;
504*726fad2aSDina K Nimeh goto clean1;
505*726fad2aSDina K Nimeh }
506*726fad2aSDina K Nimeh bytestring2bignum(&msg, data, DSA_SUBPRIME_BYTES);
507*726fad2aSDina K Nimeh
508*726fad2aSDina K Nimeh if (big_init(&tmp1, 2 * CHARLEN2BIGNUMLEN(prime_bytes)) != BIG_OK) {
509*726fad2aSDina K Nimeh rv = CKR_HOST_MEMORY;
510*726fad2aSDina K Nimeh goto clean2;
511*726fad2aSDina K Nimeh }
512*726fad2aSDina K Nimeh if (big_init(&tmp2, CHARLEN2BIGNUMLEN(prime_bytes)) != BIG_OK) {
513*726fad2aSDina K Nimeh rv = CKR_HOST_MEMORY;
514*726fad2aSDina K Nimeh goto clean3;
515*726fad2aSDina K Nimeh }
516*726fad2aSDina K Nimeh if (big_init(&tmp3, 2 * BIG_CHUNKS_FOR_160BITS) != BIG_OK) {
517*726fad2aSDina K Nimeh rv = CKR_HOST_MEMORY;
518*726fad2aSDina K Nimeh goto clean4;
519*726fad2aSDina K Nimeh }
520*726fad2aSDina K Nimeh
521*726fad2aSDina K Nimeh /*
522*726fad2aSDina K Nimeh * Verify signature against msg.
523*726fad2aSDina K Nimeh */
524*726fad2aSDina K Nimeh if (big_ext_gcd_pos(NULL, &tmp2, NULL, &(dsakey.s), &(dsakey.q)) !=
525*726fad2aSDina K Nimeh BIG_OK) {
526*726fad2aSDina K Nimeh rv = convert_rv(brv);
527*726fad2aSDina K Nimeh goto clean5;
528*726fad2aSDina K Nimeh }
529*726fad2aSDina K Nimeh
530*726fad2aSDina K Nimeh if (tmp2.sign == -1)
531*726fad2aSDina K Nimeh if (big_add(&tmp2, &tmp2, &(dsakey.q)) != BIG_OK) {
532*726fad2aSDina K Nimeh rv = convert_rv(brv);
533*726fad2aSDina K Nimeh goto clean5; /* tmp2 <- w */
534*726fad2aSDina K Nimeh }
535*726fad2aSDina K Nimeh
536*726fad2aSDina K Nimeh if (big_mul(&tmp1, &msg, &tmp2) != BIG_OK) {
537*726fad2aSDina K Nimeh rv = convert_rv(brv);
538*726fad2aSDina K Nimeh goto clean5;
539*726fad2aSDina K Nimeh }
540*726fad2aSDina K Nimeh
541*726fad2aSDina K Nimeh if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.q)) != BIG_OK) {
542*726fad2aSDina K Nimeh rv = convert_rv(brv);
543*726fad2aSDina K Nimeh goto clean5; /* tmp1 <- u_1 */
544*726fad2aSDina K Nimeh }
545*726fad2aSDina K Nimeh
546*726fad2aSDina K Nimeh if (big_mul(&tmp2, &tmp2, &(dsakey.r)) != BIG_OK) {
547*726fad2aSDina K Nimeh rv = convert_rv(brv);
548*726fad2aSDina K Nimeh goto clean5;
549*726fad2aSDina K Nimeh }
550*726fad2aSDina K Nimeh
551*726fad2aSDina K Nimeh if (big_div_pos(NULL, &tmp2, &tmp2, &(dsakey.q)) != BIG_OK) {
552*726fad2aSDina K Nimeh rv = convert_rv(brv);
553*726fad2aSDina K Nimeh goto clean5; /* tmp2 <- u_2 */
554*726fad2aSDina K Nimeh }
555*726fad2aSDina K Nimeh
556*726fad2aSDina K Nimeh if (big_modexp(&tmp1, &(dsakey.g), &tmp1, &(dsakey.p), NULL) !=
557*726fad2aSDina K Nimeh BIG_OK) {
558*726fad2aSDina K Nimeh rv = convert_rv(brv);
559*726fad2aSDina K Nimeh goto clean5;
560*726fad2aSDina K Nimeh }
561*726fad2aSDina K Nimeh
562*726fad2aSDina K Nimeh if (big_modexp(&tmp2, &(dsakey.y), &tmp2, &(dsakey.p), NULL) !=
563*726fad2aSDina K Nimeh BIG_OK) {
564*726fad2aSDina K Nimeh rv = convert_rv(brv);
565*726fad2aSDina K Nimeh goto clean5;
566*726fad2aSDina K Nimeh }
567*726fad2aSDina K Nimeh
568*726fad2aSDina K Nimeh if (big_mul(&tmp1, &tmp1, &tmp2) != BIG_OK) {
569*726fad2aSDina K Nimeh rv = convert_rv(brv);
570*726fad2aSDina K Nimeh goto clean5;
571*726fad2aSDina K Nimeh }
572*726fad2aSDina K Nimeh
573*726fad2aSDina K Nimeh if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.p)) != BIG_OK) {
574*726fad2aSDina K Nimeh rv = convert_rv(brv);
575*726fad2aSDina K Nimeh goto clean5;
576*726fad2aSDina K Nimeh }
577*726fad2aSDina K Nimeh
578*726fad2aSDina K Nimeh if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.q)) != BIG_OK) {
579*726fad2aSDina K Nimeh rv = convert_rv(brv);
580*726fad2aSDina K Nimeh goto clean5;
581*726fad2aSDina K Nimeh }
582*726fad2aSDina K Nimeh
583*726fad2aSDina K Nimeh if (big_cmp_abs(&tmp1, &(dsakey.r)) == 0)
584*726fad2aSDina K Nimeh rv = CKR_OK;
585*726fad2aSDina K Nimeh else
586*726fad2aSDina K Nimeh rv = CKR_SIGNATURE_INVALID;
587*726fad2aSDina K Nimeh
588*726fad2aSDina K Nimeh clean5:
589*726fad2aSDina K Nimeh big_finish(&tmp3);
590*726fad2aSDina K Nimeh clean4:
591*726fad2aSDina K Nimeh big_finish(&tmp2);
592*726fad2aSDina K Nimeh clean3:
593*726fad2aSDina K Nimeh big_finish(&tmp1);
594*726fad2aSDina K Nimeh clean2:
595*726fad2aSDina K Nimeh big_finish(&msg);
596*726fad2aSDina K Nimeh clean1:
597*726fad2aSDina K Nimeh DSA_key_finish(&dsakey);
598*726fad2aSDina K Nimeh
599*726fad2aSDina K Nimeh return (rv);
600*726fad2aSDina K Nimeh }
601