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/sha1.h>
35 #define	_SHA2_IMPL
36 #include <sys/sha2.h>
37 #include <sys/crypto/common.h>
38 #include <modes/modes.h>
39 #include <bignum.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <strings.h>
43 #include <stdio.h>
44 #include <security/cryptoki.h>
45 #include <cryptoutil.h>
46 #include "softCrypt.h"
47 #include "softGlobal.h"
48 #include "softRSA.h"
49 #include "softDSA.h"
50 #include "softRandom.h"
51 #include "softOps.h"
52 #include "softMAC.h"
53 #include <fips_post.h>
54 
55 #define	FIPS_DSA_SIGNATURE_LENGTH	40 /*  320-bits */
56 #define	MAX_ECKEY_LEN		72
57 
58 
59 /*
60  * FIPS 140-2 pairwise consistency check utilized to validate key pair.
61  *
62  * This function returns
63  *   CKR_OK               if pairwise consistency check passed
64  *   CKR_GENERAL_ERROR    if pairwise consistency check failed
65  *   other error codes    if paiswise consistency check could not be
66  *                        performed, for example, CKR_HOST_MEMORY.
67  *
68  *                      Key type    Mechanism type
69  *                      --------------------------------
70  *
71  * For sign/verify:     CKK_RSA  => CKM_SHA1_RSA_PKCS
72  *                      CKK_DSA  => CKM_DSA_SHA1
73  *                      CKK_EC   => CKM_ECDSA_SHA1
74  *                      others   => CKM_INVALID_MECHANISM
75  *
76  * None of these mechanisms has a parameter.
77  */
78 CK_RV
79 fips_pairwise_check(soft_session_t *session_p,
80 	soft_object_t *publicKey, soft_object_t *privateKey,
81 	CK_KEY_TYPE keyType)
82 {
83 
84 	CK_MECHANISM mech = {0, NULL, 0};
85 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
86 	uint32_t modulus_len = sizeof (modulus);
87 	boolean_t can_sign_verify = B_FALSE;
88 	CK_RV rv;
89 
90 	/* Variables used for Signature/Verification functions. */
91 	/* always uses SHA-1 digest */
92 	unsigned char *known_digest = (unsigned char *)"OpenSolarisCommunity";
93 	unsigned char *signature;
94 	CK_ULONG signature_length;
95 
96 	if (keyType == CKK_RSA) {
97 		/* Get modulus length of private key. */
98 		rv = soft_get_private_value(privateKey, CKA_MODULUS,
99 		    modulus, &modulus_len);
100 		if (rv != CKR_OK) {
101 			return (CKR_DEVICE_ERROR);
102 		}
103 	}
104 
105 	/*
106 	 * Pairwise Consistency Check of Sign/Verify
107 	 */
108 
109 	/* Check to see if key object supports signature. */
110 	can_sign_verify = (privateKey->bool_attr_mask & SIGN_BOOL_ON);
111 
112 	if (can_sign_verify) {
113 		/* Determine length of signature. */
114 		switch (keyType) {
115 		case CKK_RSA:
116 			signature_length = modulus_len;
117 			mech.mechanism = CKM_SHA1_RSA_PKCS;
118 			break;
119 
120 		case CKK_DSA:
121 			signature_length = FIPS_DSA_SIGNATURE_LENGTH;
122 			mech.mechanism = CKM_DSA_SHA1;
123 			break;
124 
125 		case CKK_EC:
126 			signature_length = MAX_ECKEY_LEN * 2;
127 			mech.mechanism = CKM_ECDSA_SHA1;
128 			break;
129 
130 		default:
131 			return (CKR_DEVICE_ERROR);
132 		}
133 
134 		/* Allocate space for signature data. */
135 		signature = (unsigned char *) calloc(1, signature_length);
136 		if (signature == NULL) {
137 			return (CKR_HOST_MEMORY);
138 		}
139 
140 		/* Sign the known hash using the private key. */
141 		rv = soft_sign_init(session_p, &mech, privateKey);
142 		if (rv != CKR_OK) {
143 			free(signature);
144 			return (rv);
145 		}
146 
147 		rv = soft_sign(session_p, known_digest, PAIRWISE_DIGEST_LENGTH,
148 		    signature, &signature_length);
149 		if (rv != CKR_OK) {
150 			free(signature);
151 			return (rv);
152 		}
153 
154 		/* Verify the known hash using the public key. */
155 		rv = soft_verify_init(session_p, &mech, publicKey);
156 		if (rv != CKR_OK) {
157 			free(signature);
158 			return (rv);
159 		}
160 
161 		rv = soft_verify(session_p, known_digest,
162 		    PAIRWISE_DIGEST_LENGTH, signature,
163 		    signature_length);
164 
165 		/* Free signature data. */
166 		free(signature);
167 		if ((rv == CKR_SIGNATURE_LEN_RANGE) ||
168 		    (rv == CKR_SIGNATURE_INVALID)) {
169 			return (CKR_GENERAL_ERROR);
170 		}
171 
172 		if (rv != CKR_OK) {
173 			return (rv);
174 		}
175 	}
176 
177 	return (CKR_OK);
178 }
179