xref: /onnv-gate/usr/src/common/crypto/fips/fips_ecc_util.c (revision 10979:00cad6413daf)
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(&params->fieldID.u.prime, B_FALSE);
248 	SECITEM_FreeItem(&params->curve.a, B_FALSE);
249 	SECITEM_FreeItem(&params->curve.b, B_FALSE);
250 	SECITEM_FreeItem(&params->curve.seed, B_FALSE);
251 	SECITEM_FreeItem(&params->base, B_FALSE);
252 	SECITEM_FreeItem(&params->order, B_FALSE);
253 	SECITEM_FreeItem(&params->DEREncoding, B_FALSE);
254 	SECITEM_FreeItem(&params->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