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 void free_ecparams(ECParams *, boolean_t);
54 static void free_ecprivkey(ECPrivateKey *);
55 static void free_ecpubkey(ECPublicKey *);
56
57 static int
fips_ecdsa_sign_verify(uint8_t * encodedParams,unsigned int encodedParamsLen,uint8_t * knownSignature,unsigned int knownSignatureLen)58 fips_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
188 loser:
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
209 int
210 fips_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
244 static void
245 free_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
263 static void
264 free_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
278 static void
279 free_ecpubkey(ECPublicKey *key)
280 {
281 free_ecparams(&key->ecParams, B_FALSE);
282 }
283