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(&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
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