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