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 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 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 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 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 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 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 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