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