1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * This file contains RSA helper routines common to 31*0Sstevel@tonic-gate * the PKCS11 soft token code and the kernel RSA code. 32*0Sstevel@tonic-gate */ 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate #include <sys/types.h> 35*0Sstevel@tonic-gate #include "rsa_impl.h" 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #ifdef _KERNEL 38*0Sstevel@tonic-gate #include <sys/param.h> 39*0Sstevel@tonic-gate #else 40*0Sstevel@tonic-gate #include <strings.h> 41*0Sstevel@tonic-gate #include "softRandom.h" 42*0Sstevel@tonic-gate #endif 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate /* 45*0Sstevel@tonic-gate * DER encoding T of the DigestInfo values for MD5 and SHA1 46*0Sstevel@tonic-gate * from PKCS#1 v2.1: RSA Cryptography Standard Section 9.2 Note 1 47*0Sstevel@tonic-gate * 48*0Sstevel@tonic-gate * MD5: (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 || H 49*0Sstevel@tonic-gate * SHA-1: (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H 50*0Sstevel@tonic-gate * 51*0Sstevel@tonic-gate * Where H is the digested output from MD5 or SHA1. We define the constant 52*0Sstevel@tonic-gate * byte array (the prefix) here and use it rather than doing the DER 53*0Sstevel@tonic-gate * encoding of the OID in a separate routine. 54*0Sstevel@tonic-gate */ 55*0Sstevel@tonic-gate const CK_BYTE MD5_DER_PREFIX[MD5_DER_PREFIX_Len] = {0x30, 0x20, 0x30, 0x0c, 56*0Sstevel@tonic-gate 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 57*0Sstevel@tonic-gate 0x04, 0x10}; 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate const CK_BYTE SHA1_DER_PREFIX[SHA1_DER_PREFIX_Len] = {0x30, 0x21, 0x30, 60*0Sstevel@tonic-gate 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}; 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate BIG_ERR_CODE 63*0Sstevel@tonic-gate RSA_key_init(RSAkey *key, int psize, int qsize) 64*0Sstevel@tonic-gate { 65*0Sstevel@tonic-gate BIG_ERR_CODE err = BIG_OK; 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate /* EXPORT DELETE START */ 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate int plen, qlen, nlen; 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate plen = (psize + 31) / 32; 72*0Sstevel@tonic-gate qlen = (qsize + 31) / 32; 73*0Sstevel@tonic-gate nlen = plen + qlen; 74*0Sstevel@tonic-gate key->size = psize + qsize; 75*0Sstevel@tonic-gate if ((err = big_init(&(key->p), plen)) != BIG_OK) 76*0Sstevel@tonic-gate return (err); 77*0Sstevel@tonic-gate if ((err = big_init(&(key->q), qlen)) != BIG_OK) 78*0Sstevel@tonic-gate goto ret1; 79*0Sstevel@tonic-gate if ((err = big_init(&(key->n), nlen)) != BIG_OK) 80*0Sstevel@tonic-gate goto ret2; 81*0Sstevel@tonic-gate if ((err = big_init(&(key->d), nlen)) != BIG_OK) 82*0Sstevel@tonic-gate goto ret3; 83*0Sstevel@tonic-gate if ((err = big_init(&(key->e), nlen)) != BIG_OK) 84*0Sstevel@tonic-gate goto ret4; 85*0Sstevel@tonic-gate if ((err = big_init(&(key->dmodpminus1), plen)) != BIG_OK) 86*0Sstevel@tonic-gate goto ret5; 87*0Sstevel@tonic-gate if ((err = big_init(&(key->dmodqminus1), qlen)) != BIG_OK) 88*0Sstevel@tonic-gate goto ret6; 89*0Sstevel@tonic-gate if ((err = big_init(&(key->pinvmodq), qlen)) != BIG_OK) 90*0Sstevel@tonic-gate goto ret7; 91*0Sstevel@tonic-gate if ((err = big_init(&(key->p_rr), plen)) != BIG_OK) 92*0Sstevel@tonic-gate goto ret8; 93*0Sstevel@tonic-gate if ((err = big_init(&(key->q_rr), qlen)) != BIG_OK) 94*0Sstevel@tonic-gate goto ret9; 95*0Sstevel@tonic-gate if ((err = big_init(&(key->n_rr), nlen)) != BIG_OK) 96*0Sstevel@tonic-gate goto ret10; 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate return (BIG_OK); 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate ret10: 101*0Sstevel@tonic-gate big_finish(&(key->q_rr)); 102*0Sstevel@tonic-gate ret9: 103*0Sstevel@tonic-gate big_finish(&(key->p_rr)); 104*0Sstevel@tonic-gate ret8: 105*0Sstevel@tonic-gate big_finish(&(key->pinvmodq)); 106*0Sstevel@tonic-gate ret7: 107*0Sstevel@tonic-gate big_finish(&(key->dmodqminus1)); 108*0Sstevel@tonic-gate ret6: 109*0Sstevel@tonic-gate big_finish(&(key->dmodpminus1)); 110*0Sstevel@tonic-gate ret5: 111*0Sstevel@tonic-gate big_finish(&(key->e)); 112*0Sstevel@tonic-gate ret4: 113*0Sstevel@tonic-gate big_finish(&(key->d)); 114*0Sstevel@tonic-gate ret3: 115*0Sstevel@tonic-gate big_finish(&(key->n)); 116*0Sstevel@tonic-gate ret2: 117*0Sstevel@tonic-gate big_finish(&(key->q)); 118*0Sstevel@tonic-gate ret1: 119*0Sstevel@tonic-gate big_finish(&(key->p)); 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate /* EXPORT DELETE END */ 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate return (err); 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate void 128*0Sstevel@tonic-gate RSA_key_finish(RSAkey *key) 129*0Sstevel@tonic-gate { 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate /* EXPORT DELETE START */ 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate big_finish(&(key->n_rr)); 134*0Sstevel@tonic-gate big_finish(&(key->q_rr)); 135*0Sstevel@tonic-gate big_finish(&(key->p_rr)); 136*0Sstevel@tonic-gate big_finish(&(key->pinvmodq)); 137*0Sstevel@tonic-gate big_finish(&(key->dmodqminus1)); 138*0Sstevel@tonic-gate big_finish(&(key->dmodpminus1)); 139*0Sstevel@tonic-gate big_finish(&(key->e)); 140*0Sstevel@tonic-gate big_finish(&(key->d)); 141*0Sstevel@tonic-gate big_finish(&(key->n)); 142*0Sstevel@tonic-gate big_finish(&(key->q)); 143*0Sstevel@tonic-gate big_finish(&(key->p)); 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate /* EXPORT DELETE END */ 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate /* 151*0Sstevel@tonic-gate * To create a block type "02" encryption block for RSA PKCS encryption 152*0Sstevel@tonic-gate * process. 153*0Sstevel@tonic-gate * 154*0Sstevel@tonic-gate * The RSA PKCS Padding before encryption is in the following format: 155*0Sstevel@tonic-gate * +------+--------------------+----+-----------------------------+ 156*0Sstevel@tonic-gate * |0x0002| 8 bytes or more RN |0x00| DATA | 157*0Sstevel@tonic-gate * +------+--------------------+----+-----------------------------+ 158*0Sstevel@tonic-gate * 159*0Sstevel@tonic-gate */ 160*0Sstevel@tonic-gate CK_RV 161*0Sstevel@tonic-gate soft_encrypt_rsa_pkcs_encode(uint8_t *databuf, 162*0Sstevel@tonic-gate size_t datalen, uint8_t *padbuf, size_t padbuflen) 163*0Sstevel@tonic-gate { 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate /* EXPORT DELETE START */ 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate size_t padlen; 168*0Sstevel@tonic-gate CK_RV rv; 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate padlen = padbuflen - datalen; 171*0Sstevel@tonic-gate if (padlen < MIN_PKCS1_PADLEN) { 172*0Sstevel@tonic-gate return (CKR_DATA_LEN_RANGE); 173*0Sstevel@tonic-gate } 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate /* Pad with 0x0002+non-zero pseudorandom numbers+0x00. */ 176*0Sstevel@tonic-gate padbuf[0] = 0x00; 177*0Sstevel@tonic-gate padbuf[1] = 0x02; 178*0Sstevel@tonic-gate #ifdef _KERNEL 179*0Sstevel@tonic-gate rv = knzero_random_generator(padbuf + 2, padbuflen - 3); 180*0Sstevel@tonic-gate #else 181*0Sstevel@tonic-gate rv = soft_nzero_random_generator(padbuf + 2, padbuflen - 3); 182*0Sstevel@tonic-gate #endif 183*0Sstevel@tonic-gate if (rv != CKR_OK) { 184*0Sstevel@tonic-gate return (rv); 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate padbuf[padlen - 1] = 0x00; 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate bcopy(databuf, padbuf + padlen, datalen); 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate /* EXPORT DELETE END */ 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate return (CKR_OK); 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate /* 197*0Sstevel@tonic-gate * The RSA PKCS Padding after decryption is in the following format: 198*0Sstevel@tonic-gate * +------+--------------------+----+-----------------------------+ 199*0Sstevel@tonic-gate * |0x0002| 8 bytes or more RN |0x00| DATA | 200*0Sstevel@tonic-gate * +------+--------------------+----+-----------------------------+ 201*0Sstevel@tonic-gate * 202*0Sstevel@tonic-gate * 'padbuf' points to the recovered message which is the modulus 203*0Sstevel@tonic-gate * length. As a result, 'plen' is changed to hold the actual data length. 204*0Sstevel@tonic-gate */ 205*0Sstevel@tonic-gate CK_RV 206*0Sstevel@tonic-gate soft_decrypt_rsa_pkcs_decode(uint8_t *padbuf, int *plen) 207*0Sstevel@tonic-gate { 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate /* EXPORT DELETE START */ 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate int i; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* Check to see if the recovered data is padded is 0x0002. */ 214*0Sstevel@tonic-gate if (padbuf[0] != 0x00 || padbuf[1] != 0x02) { 215*0Sstevel@tonic-gate return (CKR_ENCRYPTED_DATA_INVALID); 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate /* Remove all the random bits up to 0x00 (= NULL char) */ 219*0Sstevel@tonic-gate for (i = 2; (*plen - i) > 0; i++) { 220*0Sstevel@tonic-gate if (padbuf[i] == 0x00) { 221*0Sstevel@tonic-gate i++; 222*0Sstevel@tonic-gate if (i < MIN_PKCS1_PADLEN) { 223*0Sstevel@tonic-gate return (CKR_ENCRYPTED_DATA_INVALID); 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate *plen -= i; 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate return (CKR_OK); 228*0Sstevel@tonic-gate } 229*0Sstevel@tonic-gate } 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate /* EXPORT DELETE END */ 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate return (CKR_ENCRYPTED_DATA_INVALID); 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate /* 237*0Sstevel@tonic-gate * To create a block type "01" block for RSA PKCS signature process. 238*0Sstevel@tonic-gate * 239*0Sstevel@tonic-gate * The RSA PKCS Padding before Signing is in the following format: 240*0Sstevel@tonic-gate * +------+--------------+----+-----------------------------+ 241*0Sstevel@tonic-gate * |0x0001| 0xFFFF.......|0x00| DATA | 242*0Sstevel@tonic-gate * +------+--------------+----+-----------------------------+ 243*0Sstevel@tonic-gate */ 244*0Sstevel@tonic-gate CK_RV 245*0Sstevel@tonic-gate soft_sign_rsa_pkcs_encode(uint8_t *pData, size_t dataLen, uint8_t *data, 246*0Sstevel@tonic-gate size_t mbit_l) 247*0Sstevel@tonic-gate { 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate /* EXPORT DELETE START */ 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate size_t padlen; 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate padlen = mbit_l - dataLen; 254*0Sstevel@tonic-gate if (padlen < MIN_PKCS1_PADLEN) { 255*0Sstevel@tonic-gate return (CKR_DATA_LEN_RANGE); 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate padlen -= 3; 259*0Sstevel@tonic-gate data[0] = 0x00; 260*0Sstevel@tonic-gate data[1] = 0x01; 261*0Sstevel@tonic-gate #ifdef _KERNEL 262*0Sstevel@tonic-gate kmemset(data + 2, 0xFF, padlen); 263*0Sstevel@tonic-gate #else 264*0Sstevel@tonic-gate (void) memset(data + 2, 0xFF, padlen); 265*0Sstevel@tonic-gate #endif 266*0Sstevel@tonic-gate data[padlen + 2] = 0x00; 267*0Sstevel@tonic-gate bcopy(pData, data + padlen + 3, dataLen); 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate /* EXPORT DELETE END */ 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate return (CKR_OK); 272*0Sstevel@tonic-gate } 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate CK_RV 276*0Sstevel@tonic-gate soft_verify_rsa_pkcs_decode(uint8_t *data, int *mbit_l) 277*0Sstevel@tonic-gate { 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate /* EXPORT DELETE START */ 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate int i; 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate /* Check to see if the padding of recovered data starts with 0x0001. */ 284*0Sstevel@tonic-gate if ((data[0] != 0x00) || (data[1] != 0x01)) { 285*0Sstevel@tonic-gate return (CKR_SIGNATURE_INVALID); 286*0Sstevel@tonic-gate } 287*0Sstevel@tonic-gate /* Check to see if the recovered data is padded with 0xFFF...00. */ 288*0Sstevel@tonic-gate for (i = 2; i < *mbit_l; i++) { 289*0Sstevel@tonic-gate if (data[i] == 0x00) { 290*0Sstevel@tonic-gate i++; 291*0Sstevel@tonic-gate if (i < MIN_PKCS1_PADLEN) { 292*0Sstevel@tonic-gate return (CKR_SIGNATURE_INVALID); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate *mbit_l -= i; 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate return (CKR_OK); 297*0Sstevel@tonic-gate } else if (data[i] != 0xFF) { 298*0Sstevel@tonic-gate return (CKR_SIGNATURE_INVALID); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate /* EXPORT DELETE END */ 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate return (CKR_SIGNATURE_INVALID); 305*0Sstevel@tonic-gate } 306