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