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