1*10500SHai-May.Chao@Sun.COM /* 2*10500SHai-May.Chao@Sun.COM * CDDL HEADER START 3*10500SHai-May.Chao@Sun.COM * 4*10500SHai-May.Chao@Sun.COM * The contents of this file are subject to the terms of the 5*10500SHai-May.Chao@Sun.COM * Common Development and Distribution License (the "License"). 6*10500SHai-May.Chao@Sun.COM * You may not use this file except in compliance with the License. 7*10500SHai-May.Chao@Sun.COM * 8*10500SHai-May.Chao@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*10500SHai-May.Chao@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*10500SHai-May.Chao@Sun.COM * See the License for the specific language governing permissions 11*10500SHai-May.Chao@Sun.COM * and limitations under the License. 12*10500SHai-May.Chao@Sun.COM * 13*10500SHai-May.Chao@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*10500SHai-May.Chao@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*10500SHai-May.Chao@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*10500SHai-May.Chao@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*10500SHai-May.Chao@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*10500SHai-May.Chao@Sun.COM * 19*10500SHai-May.Chao@Sun.COM * CDDL HEADER END 20*10500SHai-May.Chao@Sun.COM */ 21*10500SHai-May.Chao@Sun.COM /* 22*10500SHai-May.Chao@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*10500SHai-May.Chao@Sun.COM * Use is subject to license terms. 24*10500SHai-May.Chao@Sun.COM */ 25*10500SHai-May.Chao@Sun.COM 26*10500SHai-May.Chao@Sun.COM #include <sys/types.h> 27*10500SHai-May.Chao@Sun.COM #include <sys/errno.h> 28*10500SHai-May.Chao@Sun.COM #include <sys/fcntl.h> 29*10500SHai-May.Chao@Sun.COM #include <sys/time.h> 30*10500SHai-May.Chao@Sun.COM #include <sys/unistd.h> 31*10500SHai-May.Chao@Sun.COM #include <sys/kmem.h> 32*10500SHai-May.Chao@Sun.COM #include <sys/systm.h> 33*10500SHai-May.Chao@Sun.COM #include <sys/sysmacros.h> 34*10500SHai-May.Chao@Sun.COM #include <sys/crypto/common.h> 35*10500SHai-May.Chao@Sun.COM #include <sys/cmn_err.h> 36*10500SHai-May.Chao@Sun.COM #include <sys/sha1.h> 37*10500SHai-May.Chao@Sun.COM #ifndef _KERNEL 38*10500SHai-May.Chao@Sun.COM #include <stdlib.h> 39*10500SHai-May.Chao@Sun.COM #include <string.h> 40*10500SHai-May.Chao@Sun.COM #include <strings.h> 41*10500SHai-May.Chao@Sun.COM #include <stdio.h> 42*10500SHai-May.Chao@Sun.COM #include <security/cryptoki.h> 43*10500SHai-May.Chao@Sun.COM #include "softMAC.h" 44*10500SHai-May.Chao@Sun.COM #include "softEC.h" 45*10500SHai-May.Chao@Sun.COM #endif 46*10500SHai-May.Chao@Sun.COM #include <fips/fips_post.h> 47*10500SHai-May.Chao@Sun.COM #include <ecc/ecc_impl.h> 48*10500SHai-May.Chao@Sun.COM 49*10500SHai-May.Chao@Sun.COM 50*10500SHai-May.Chao@Sun.COM #define MAX_ECKEY_LEN 72 51*10500SHai-May.Chao@Sun.COM #define SHA1_DIGEST_SIZE 20 52*10500SHai-May.Chao@Sun.COM 53*10500SHai-May.Chao@Sun.COM static int 54*10500SHai-May.Chao@Sun.COM fips_ecdsa_sign_verify(uint8_t *encodedParams, 55*10500SHai-May.Chao@Sun.COM unsigned int encodedParamsLen, 56*10500SHai-May.Chao@Sun.COM uint8_t *knownSignature, 57*10500SHai-May.Chao@Sun.COM unsigned int knownSignatureLen) { 58*10500SHai-May.Chao@Sun.COM 59*10500SHai-May.Chao@Sun.COM /* ECDSA Known Seed info for curves nistp256 */ 60*10500SHai-May.Chao@Sun.COM static uint8_t ecdsa_Known_Seed[] = { 61*10500SHai-May.Chao@Sun.COM 0x6a, 0x9b, 0xf6, 0xf7, 0xce, 0xed, 0x79, 0x11, 62*10500SHai-May.Chao@Sun.COM 0xf0, 0xc7, 0xc8, 0x9a, 0xa5, 0xd1, 0x57, 0xb1, 63*10500SHai-May.Chao@Sun.COM 0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc, 64*10500SHai-May.Chao@Sun.COM 0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f 65*10500SHai-May.Chao@Sun.COM }; 66*10500SHai-May.Chao@Sun.COM 67*10500SHai-May.Chao@Sun.COM static uint8_t msg[] = { 68*10500SHai-May.Chao@Sun.COM "Sun Microsystems Solaris is awesome!" 69*10500SHai-May.Chao@Sun.COM }; 70*10500SHai-May.Chao@Sun.COM 71*10500SHai-May.Chao@Sun.COM unsigned char sha1[SHA1_DIGEST_SIZE]; /* SHA-1 hash (160 bits) */ 72*10500SHai-May.Chao@Sun.COM unsigned char sig[2*MAX_ECKEY_LEN]; 73*10500SHai-May.Chao@Sun.COM SECItem signature, digest; 74*10500SHai-May.Chao@Sun.COM SECItem encodedparams; 75*10500SHai-May.Chao@Sun.COM ECParams *ecparams = NULL; 76*10500SHai-May.Chao@Sun.COM ECPrivateKey *ecdsa_private_key = NULL; 77*10500SHai-May.Chao@Sun.COM ECPublicKey ecdsa_public_key; 78*10500SHai-May.Chao@Sun.COM SECStatus ecdsaStatus = SECSuccess; 79*10500SHai-May.Chao@Sun.COM SHA1_CTX *sha1_context = NULL; 80*10500SHai-May.Chao@Sun.COM 81*10500SHai-May.Chao@Sun.COM /* construct the ECDSA private/public key pair */ 82*10500SHai-May.Chao@Sun.COM encodedparams.type = siBuffer; 83*10500SHai-May.Chao@Sun.COM encodedparams.data = (unsigned char *) encodedParams; 84*10500SHai-May.Chao@Sun.COM encodedparams.len = encodedParamsLen; 85*10500SHai-May.Chao@Sun.COM 86*10500SHai-May.Chao@Sun.COM if (EC_DecodeParams(&encodedparams, &ecparams, 0) != SECSuccess) { 87*10500SHai-May.Chao@Sun.COM return (CKR_ARGUMENTS_BAD); 88*10500SHai-May.Chao@Sun.COM } 89*10500SHai-May.Chao@Sun.COM 90*10500SHai-May.Chao@Sun.COM /* 91*10500SHai-May.Chao@Sun.COM * Generates a new EC key pair. The private key is a supplied 92*10500SHai-May.Chao@Sun.COM * random value (in seed) and the public key is the result of 93*10500SHai-May.Chao@Sun.COM * performing a scalar point multiplication of that value with 94*10500SHai-May.Chao@Sun.COM * the curve's base point. 95*10500SHai-May.Chao@Sun.COM */ 96*10500SHai-May.Chao@Sun.COM 97*10500SHai-May.Chao@Sun.COM ecdsaStatus = ec_NewKey(ecparams, &ecdsa_private_key, 98*10500SHai-May.Chao@Sun.COM ecdsa_Known_Seed, sizeof (ecdsa_Known_Seed), 0); 99*10500SHai-May.Chao@Sun.COM 100*10500SHai-May.Chao@Sun.COM if (ecdsaStatus != SECSuccess) { 101*10500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR); 102*10500SHai-May.Chao@Sun.COM } 103*10500SHai-May.Chao@Sun.COM 104*10500SHai-May.Chao@Sun.COM /* construct public key from private key. */ 105*10500SHai-May.Chao@Sun.COM ecdsaStatus = EC_CopyParams(ecdsa_private_key->ecParams.arena, 106*10500SHai-May.Chao@Sun.COM &ecdsa_public_key.ecParams, &ecdsa_private_key->ecParams); 107*10500SHai-May.Chao@Sun.COM 108*10500SHai-May.Chao@Sun.COM if (ecdsaStatus != SECSuccess) { 109*10500SHai-May.Chao@Sun.COM goto loser; 110*10500SHai-May.Chao@Sun.COM } 111*10500SHai-May.Chao@Sun.COM 112*10500SHai-May.Chao@Sun.COM ecdsa_public_key.publicValue = ecdsa_private_key->publicValue; 113*10500SHai-May.Chao@Sun.COM 114*10500SHai-May.Chao@Sun.COM /* validate public key value */ 115*10500SHai-May.Chao@Sun.COM ecdsaStatus = EC_ValidatePublicKey(&ecdsa_public_key.ecParams, 116*10500SHai-May.Chao@Sun.COM &ecdsa_public_key.publicValue, 0); 117*10500SHai-May.Chao@Sun.COM 118*10500SHai-May.Chao@Sun.COM if (ecdsaStatus != SECSuccess) { 119*10500SHai-May.Chao@Sun.COM goto loser; 120*10500SHai-May.Chao@Sun.COM } 121*10500SHai-May.Chao@Sun.COM 122*10500SHai-May.Chao@Sun.COM /* validate public key value */ 123*10500SHai-May.Chao@Sun.COM ecdsaStatus = EC_ValidatePublicKey(&ecdsa_private_key->ecParams, 124*10500SHai-May.Chao@Sun.COM &ecdsa_private_key->publicValue, 0); 125*10500SHai-May.Chao@Sun.COM 126*10500SHai-May.Chao@Sun.COM if (ecdsaStatus != SECSuccess) { 127*10500SHai-May.Chao@Sun.COM goto loser; 128*10500SHai-May.Chao@Sun.COM } 129*10500SHai-May.Chao@Sun.COM 130*10500SHai-May.Chao@Sun.COM /* 131*10500SHai-May.Chao@Sun.COM * ECDSA Known Answer Signature Test. 132*10500SHai-May.Chao@Sun.COM */ 133*10500SHai-May.Chao@Sun.COM #ifdef _KERNEL 134*10500SHai-May.Chao@Sun.COM if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX), 135*10500SHai-May.Chao@Sun.COM KM_SLEEP)) == NULL) 136*10500SHai-May.Chao@Sun.COM #else 137*10500SHai-May.Chao@Sun.COM if ((sha1_context = malloc(sizeof (SHA1_CTX))) == NULL) 138*10500SHai-May.Chao@Sun.COM #endif 139*10500SHai-May.Chao@Sun.COM return (CKR_HOST_MEMORY); 140*10500SHai-May.Chao@Sun.COM 141*10500SHai-May.Chao@Sun.COM SHA1Init(sha1_context); 142*10500SHai-May.Chao@Sun.COM 143*10500SHai-May.Chao@Sun.COM #ifdef __sparcv9 144*10500SHai-May.Chao@Sun.COM SHA1Update(sha1_context, msg, (uint_t)sizeof (msg)); 145*10500SHai-May.Chao@Sun.COM #else /* !__sparcv9 */ 146*10500SHai-May.Chao@Sun.COM SHA1Update(sha1_context, msg, sizeof (msg)); 147*10500SHai-May.Chao@Sun.COM #endif /* __sparcv9 */ 148*10500SHai-May.Chao@Sun.COM SHA1Final(sha1, sha1_context); 149*10500SHai-May.Chao@Sun.COM 150*10500SHai-May.Chao@Sun.COM digest.type = siBuffer; 151*10500SHai-May.Chao@Sun.COM digest.data = sha1; 152*10500SHai-May.Chao@Sun.COM digest.len = SHA1_DIGEST_SIZE; 153*10500SHai-May.Chao@Sun.COM 154*10500SHai-May.Chao@Sun.COM (void) memset(sig, 0, sizeof (sig)); 155*10500SHai-May.Chao@Sun.COM signature.type = siBuffer; 156*10500SHai-May.Chao@Sun.COM signature.data = sig; 157*10500SHai-May.Chao@Sun.COM signature.len = sizeof (sig); 158*10500SHai-May.Chao@Sun.COM 159*10500SHai-May.Chao@Sun.COM ecdsaStatus = ECDSA_SignDigestWithSeed(ecdsa_private_key, &signature, 160*10500SHai-May.Chao@Sun.COM &digest, ecdsa_Known_Seed, sizeof (ecdsa_Known_Seed), 0); 161*10500SHai-May.Chao@Sun.COM 162*10500SHai-May.Chao@Sun.COM if (ecdsaStatus != SECSuccess) { 163*10500SHai-May.Chao@Sun.COM goto loser; 164*10500SHai-May.Chao@Sun.COM } 165*10500SHai-May.Chao@Sun.COM 166*10500SHai-May.Chao@Sun.COM if ((signature.len != knownSignatureLen) || 167*10500SHai-May.Chao@Sun.COM (memcmp(signature.data, knownSignature, 168*10500SHai-May.Chao@Sun.COM knownSignatureLen) != 0)) { 169*10500SHai-May.Chao@Sun.COM ecdsaStatus = SECFailure; 170*10500SHai-May.Chao@Sun.COM goto loser; 171*10500SHai-May.Chao@Sun.COM } 172*10500SHai-May.Chao@Sun.COM 173*10500SHai-May.Chao@Sun.COM /* 174*10500SHai-May.Chao@Sun.COM * ECDSA Known Answer Verification Test. 175*10500SHai-May.Chao@Sun.COM */ 176*10500SHai-May.Chao@Sun.COM ecdsaStatus = ECDSA_VerifyDigest(&ecdsa_public_key, &signature, 177*10500SHai-May.Chao@Sun.COM &digest, 0); 178*10500SHai-May.Chao@Sun.COM 179*10500SHai-May.Chao@Sun.COM loser: 180*10500SHai-May.Chao@Sun.COM if (ecdsaStatus != SECSuccess) { 181*10500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR); 182*10500SHai-May.Chao@Sun.COM } 183*10500SHai-May.Chao@Sun.COM 184*10500SHai-May.Chao@Sun.COM return (CKR_OK); 185*10500SHai-May.Chao@Sun.COM } 186*10500SHai-May.Chao@Sun.COM 187*10500SHai-May.Chao@Sun.COM int 188*10500SHai-May.Chao@Sun.COM fips_ecdsa_post() { 189*10500SHai-May.Chao@Sun.COM 190*10500SHai-May.Chao@Sun.COM /* ECDSA Known curve nistp256 == SEC_OID_SECG_EC_SECP256R1 params */ 191*10500SHai-May.Chao@Sun.COM static uint8_t ecdsa_known_P256_EncodedParams[] = { 192*10500SHai-May.Chao@Sun.COM 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 193*10500SHai-May.Chao@Sun.COM 0x01, 0x07 194*10500SHai-May.Chao@Sun.COM }; 195*10500SHai-May.Chao@Sun.COM 196*10500SHai-May.Chao@Sun.COM static uint8_t ecdsa_known_P256_signature[] = { 197*10500SHai-May.Chao@Sun.COM 0x07, 0xb1, 0xcb, 0x57, 0x20, 0xa7, 0x10, 0xd6, 198*10500SHai-May.Chao@Sun.COM 0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff, 199*10500SHai-May.Chao@Sun.COM 0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f, 200*10500SHai-May.Chao@Sun.COM 0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5, 201*10500SHai-May.Chao@Sun.COM 0x2b, 0xdb, 0x86, 0x76, 0xe7, 0x32, 0xba, 0x13, 202*10500SHai-May.Chao@Sun.COM 0x03, 0x7f, 0x7f, 0x92, 0x77, 0xd8, 0x35, 0xfe, 203*10500SHai-May.Chao@Sun.COM 0x99, 0xb4, 0xb7, 0x85, 0x5a, 0xfb, 0xfb, 0xce, 204*10500SHai-May.Chao@Sun.COM 0x5d, 0x0e, 0xbc, 0x01, 0xfa, 0x44, 0x97, 0x7e 205*10500SHai-May.Chao@Sun.COM }; 206*10500SHai-May.Chao@Sun.COM 207*10500SHai-May.Chao@Sun.COM int rv; 208*10500SHai-May.Chao@Sun.COM 209*10500SHai-May.Chao@Sun.COM /* ECDSA GF(p) prime field curve test */ 210*10500SHai-May.Chao@Sun.COM rv = fips_ecdsa_sign_verify(ecdsa_known_P256_EncodedParams, 211*10500SHai-May.Chao@Sun.COM sizeof (ecdsa_known_P256_EncodedParams), 212*10500SHai-May.Chao@Sun.COM ecdsa_known_P256_signature, 213*10500SHai-May.Chao@Sun.COM sizeof (ecdsa_known_P256_signature)); 214*10500SHai-May.Chao@Sun.COM 215*10500SHai-May.Chao@Sun.COM if (rv != CKR_OK) { 216*10500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR); 217*10500SHai-May.Chao@Sun.COM } 218*10500SHai-May.Chao@Sun.COM 219*10500SHai-May.Chao@Sun.COM return (CKR_OK); 220*10500SHai-May.Chao@Sun.COM } 221