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