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 53 static int 54 fips_ecdsa_sign_verify(uint8_t *encodedParams, 55 unsigned int encodedParamsLen, 56 uint8_t *knownSignature, 57 unsigned int knownSignatureLen) { 58 59 /* ECDSA Known Seed info for curves nistp256 */ 60 static uint8_t ecdsa_Known_Seed[] = { 61 0x6a, 0x9b, 0xf6, 0xf7, 0xce, 0xed, 0x79, 0x11, 62 0xf0, 0xc7, 0xc8, 0x9a, 0xa5, 0xd1, 0x57, 0xb1, 63 0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc, 64 0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f 65 }; 66 67 static uint8_t msg[] = { 68 "Sun Microsystems Solaris is awesome!" 69 }; 70 71 unsigned char sha1[SHA1_DIGEST_SIZE]; /* SHA-1 hash (160 bits) */ 72 unsigned char sig[2*MAX_ECKEY_LEN]; 73 SECItem signature, digest; 74 SECItem encodedparams; 75 ECParams *ecparams = NULL; 76 ECPrivateKey *ecdsa_private_key = NULL; 77 ECPublicKey ecdsa_public_key; 78 SECStatus ecdsaStatus = SECSuccess; 79 SHA1_CTX *sha1_context = NULL; 80 81 /* construct the ECDSA private/public key pair */ 82 encodedparams.type = siBuffer; 83 encodedparams.data = (unsigned char *) encodedParams; 84 encodedparams.len = encodedParamsLen; 85 86 if (EC_DecodeParams(&encodedparams, &ecparams, 0) != SECSuccess) { 87 return (CKR_ARGUMENTS_BAD); 88 } 89 90 /* 91 * Generates a new EC key pair. The private key is a supplied 92 * random value (in seed) and the public key is the result of 93 * performing a scalar point multiplication of that value with 94 * the curve's base point. 95 */ 96 97 ecdsaStatus = ec_NewKey(ecparams, &ecdsa_private_key, 98 ecdsa_Known_Seed, sizeof (ecdsa_Known_Seed), 0); 99 100 if (ecdsaStatus != SECSuccess) { 101 return (CKR_DEVICE_ERROR); 102 } 103 104 /* construct public key from private key. */ 105 ecdsaStatus = EC_CopyParams(ecdsa_private_key->ecParams.arena, 106 &ecdsa_public_key.ecParams, &ecdsa_private_key->ecParams); 107 108 if (ecdsaStatus != SECSuccess) { 109 goto loser; 110 } 111 112 ecdsa_public_key.publicValue = ecdsa_private_key->publicValue; 113 114 /* validate public key value */ 115 ecdsaStatus = EC_ValidatePublicKey(&ecdsa_public_key.ecParams, 116 &ecdsa_public_key.publicValue, 0); 117 118 if (ecdsaStatus != SECSuccess) { 119 goto loser; 120 } 121 122 /* validate public key value */ 123 ecdsaStatus = EC_ValidatePublicKey(&ecdsa_private_key->ecParams, 124 &ecdsa_private_key->publicValue, 0); 125 126 if (ecdsaStatus != SECSuccess) { 127 goto loser; 128 } 129 130 /* 131 * ECDSA Known Answer Signature Test. 132 */ 133 #ifdef _KERNEL 134 if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX), 135 KM_SLEEP)) == NULL) 136 #else 137 if ((sha1_context = malloc(sizeof (SHA1_CTX))) == NULL) 138 #endif 139 return (CKR_HOST_MEMORY); 140 141 SHA1Init(sha1_context); 142 143 #ifdef __sparcv9 144 SHA1Update(sha1_context, msg, (uint_t)sizeof (msg)); 145 #else /* !__sparcv9 */ 146 SHA1Update(sha1_context, msg, sizeof (msg)); 147 #endif /* __sparcv9 */ 148 SHA1Final(sha1, sha1_context); 149 150 digest.type = siBuffer; 151 digest.data = sha1; 152 digest.len = SHA1_DIGEST_SIZE; 153 154 (void) memset(sig, 0, sizeof (sig)); 155 signature.type = siBuffer; 156 signature.data = sig; 157 signature.len = sizeof (sig); 158 159 ecdsaStatus = ECDSA_SignDigestWithSeed(ecdsa_private_key, &signature, 160 &digest, ecdsa_Known_Seed, sizeof (ecdsa_Known_Seed), 0); 161 162 if (ecdsaStatus != SECSuccess) { 163 goto loser; 164 } 165 166 if ((signature.len != knownSignatureLen) || 167 (memcmp(signature.data, knownSignature, 168 knownSignatureLen) != 0)) { 169 ecdsaStatus = SECFailure; 170 goto loser; 171 } 172 173 /* 174 * ECDSA Known Answer Verification Test. 175 */ 176 ecdsaStatus = ECDSA_VerifyDigest(&ecdsa_public_key, &signature, 177 &digest, 0); 178 179 loser: 180 if (ecdsaStatus != SECSuccess) { 181 return (CKR_DEVICE_ERROR); 182 } 183 184 return (CKR_OK); 185 } 186 187 int 188 fips_ecdsa_post() { 189 190 /* ECDSA Known curve nistp256 == SEC_OID_SECG_EC_SECP256R1 params */ 191 static uint8_t ecdsa_known_P256_EncodedParams[] = { 192 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 193 0x01, 0x07 194 }; 195 196 static uint8_t ecdsa_known_P256_signature[] = { 197 0x07, 0xb1, 0xcb, 0x57, 0x20, 0xa7, 0x10, 0xd6, 198 0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff, 199 0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f, 200 0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5, 201 0x2b, 0xdb, 0x86, 0x76, 0xe7, 0x32, 0xba, 0x13, 202 0x03, 0x7f, 0x7f, 0x92, 0x77, 0xd8, 0x35, 0xfe, 203 0x99, 0xb4, 0xb7, 0x85, 0x5a, 0xfb, 0xfb, 0xce, 204 0x5d, 0x0e, 0xbc, 0x01, 0xfa, 0x44, 0x97, 0x7e 205 }; 206 207 int rv; 208 209 /* ECDSA GF(p) prime field curve test */ 210 rv = fips_ecdsa_sign_verify(ecdsa_known_P256_EncodedParams, 211 sizeof (ecdsa_known_P256_EncodedParams), 212 ecdsa_known_P256_signature, 213 sizeof (ecdsa_known_P256_signature)); 214 215 if (rv != CKR_OK) { 216 return (CKR_DEVICE_ERROR); 217 } 218 219 return (CKR_OK); 220 } 221