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