xref: /onnv-gate/usr/src/common/crypto/fips/fips_ecc_util.c (revision 10500:a10fbcfc2f21)
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