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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <stdio.h>
29 #include <link.h>
30 #include <fcntl.h>
31 #include <ctype.h>
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <ber_der.h>
36 #include <kmfapiP.h>
37 #include <libgen.h>
38 #include <cryptoutil.h>
39 
40 /*
41  *
42  * Name: KMF_SignDataWithKey
43  *
44  * Description:
45  *   This function signs a block of data using the private key
46  * and returns the signature in output
47  *
48  * Parameters:
49  *   handle(input) - opaque handle for KMF session
50  *   key(input) - contains private key handle needed for signing
51  *   AlgOID(input) - contains algorithm to be used for signing
52  *   tobesigned(input) - pointer to a KMF_DATA structure containing
53  *		the data to be signed
54  *   output(output) - pointer to the KMF_DATA structure containing the
55  *		signed data
56  *
57  * Returns:
58  *   A KMF_RETURN value indicating success or specifying a particular
59  * error condition.
60  *   The value KMF_OK indicates success. All other values represent
61  * an error condition.
62  *
63  */
64 KMF_RETURN
65 KMF_SignDataWithKey(KMF_HANDLE_T handle,
66 	KMF_KEY_HANDLE *key,
67 	KMF_OID *AlgOID,
68 	KMF_DATA *tobesigned,
69 	KMF_DATA *output)
70 {
71 	KMF_RETURN ret;
72 	KMF_PLUGIN *plugin;
73 	KMF_ALGORITHM_INDEX AlgId;
74 	KMF_DATA	signature = {0, NULL};
75 
76 	CLEAR_ERROR(handle, ret);
77 	if (ret != KMF_OK)
78 		return (ret);
79 
80 	if (key == NULL || AlgOID == NULL ||
81 		tobesigned == NULL || output == NULL)
82 		return (KMF_ERR_BAD_PARAMETER);
83 
84 	/*
85 	 * The plugin must be based on the key since private keys
86 	 * cannot be extracted.
87 	 */
88 	plugin = FindPlugin(handle, key->kstype);
89 	if (plugin != NULL && plugin->funclist->SignData != NULL) {
90 		ret = plugin->funclist->SignData(handle, key,
91 		    AlgOID, tobesigned, output);
92 		if (ret != KMF_OK)
93 			goto cleanup;
94 
95 		AlgId = X509_AlgorithmOidToAlgId(AlgOID);
96 
97 		/*
98 		 * For DSA, NSS returns an encoded signature. Decode the
99 		 * signature as DSA signature should be 40-byte long.
100 		 */
101 		if ((AlgId == KMF_ALGID_SHA1WithDSA) &&
102 		    (plugin->type == KMF_KEYSTORE_NSS)) {
103 			ret = DerDecodeDSASignature(output, &signature);
104 			if (ret != KMF_OK) {
105 				goto cleanup;
106 			} else {
107 				output->Length = signature.Length;
108 				(void) memcpy(output->Data, signature.Data,
109 				    signature.Length);
110 			}
111 		} else if (AlgId == KMF_ALGID_NONE) {
112 			ret = KMF_ERR_BAD_ALGORITHM;
113 		}
114 	} else {
115 		return (KMF_ERR_PLUGIN_NOTFOUND);
116 	}
117 
118 cleanup:
119 	if (signature.Data)
120 		free(signature.Data);
121 	return (ret);
122 }
123 
124 /*
125  *
126  * Name: KMF_VerifyDataWithKey
127  *
128  * Description:
129  *   This function verifies the signature of a block of data
130  * using the input public key
131  *
132  * Parameters:
133  *	handle(input) - opaque handle for KMF session
134  *	KMFKey(input) - holds public key information for verification
135  *	sigAlg(input) - algorithm to verify
136  *	indata(input) - pointer to the block of data whose signature
137  *		is to be verified
138  *	insig(input) - pointer to the signature to be verified
139  *
140  * Returns:
141  *   A KMF_RETURN value indicating success or specifying a particular
142  * error condition.
143  *   The value KMF_OK indicates success. All other values represent
144  * an error condition.
145  *
146  */
147 KMF_RETURN
148 KMF_VerifyDataWithKey(KMF_HANDLE_T handle,
149 		KMF_KEY_HANDLE *KMFKey,
150 		KMF_ALGORITHM_INDEX sigAlg,
151 		KMF_DATA *indata,
152 		KMF_DATA *insig)
153 {
154 	KMF_RETURN err;
155 	KMF_DATA	derkey = {0, NULL};
156 	KMF_PLUGIN	*plugin;
157 
158 	CLEAR_ERROR(handle, err);
159 	if (err != KMF_OK)
160 		return (err);
161 
162 	if (KMFKey == NULL ||
163 		indata == NULL || insig == NULL)
164 		return (KMF_ERR_BAD_PARAMETER);
165 
166 	plugin = FindPlugin(handle, KMFKey->kstype);
167 
168 	/* Retrieve public key data from keystore */
169 	if (plugin != NULL && plugin->funclist->EncodePubkeyData != NULL) {
170 		err = plugin->funclist->EncodePubkeyData(handle,
171 		    KMFKey, &derkey);
172 	} else {
173 		return (KMF_ERR_PLUGIN_NOTFOUND);
174 	}
175 
176 	err = VerifyDataWithKey(handle, &derkey, sigAlg, indata, insig);
177 
178 	if (derkey.Data != NULL)
179 		free(derkey.Data);
180 
181 	return (err);
182 }
183 
184 KMF_RETURN
185 KMF_CreateKeypair(KMF_HANDLE_T handle,
186 	KMF_CREATEKEYPAIR_PARAMS *params,
187 	KMF_KEY_HANDLE *privKey,
188 	KMF_KEY_HANDLE *pubKey)
189 {
190 	KMF_PLUGIN *plugin;
191 	KMF_RETURN ret;
192 
193 	CLEAR_ERROR(handle, ret);
194 	if (ret != KMF_OK)
195 		return (ret);
196 
197 	if (params == NULL ||
198 		privKey == NULL || pubKey == NULL)
199 		return (KMF_ERR_BAD_PARAMETER);
200 
201 	(void) memset(privKey, 0, sizeof (KMF_KEY_HANDLE));
202 	(void) memset(pubKey, 0, sizeof (KMF_KEY_HANDLE));
203 	plugin = FindPlugin(handle, params->kstype);
204 
205 	if (plugin != NULL && plugin->funclist->CreateKeypair != NULL) {
206 		return (plugin->funclist->CreateKeypair(handle, params,
207 			privKey, pubKey));
208 	} else {
209 		return (KMF_ERR_PLUGIN_NOTFOUND);
210 	}
211 }
212 
213 KMF_RETURN
214 KMF_DeleteKeyFromKeystore(KMF_HANDLE_T handle, KMF_DELETEKEY_PARAMS *params,
215 	KMF_KEY_HANDLE *key)
216 {
217 	KMF_RETURN rv = KMF_OK;
218 	KMF_PLUGIN *plugin;
219 
220 	CLEAR_ERROR(handle, rv);
221 	if (rv != KMF_OK)
222 		return (rv);
223 
224 	if (key == NULL || params == NULL)
225 		return (KMF_ERR_BAD_PARAMETER);
226 
227 	plugin = FindPlugin(handle, params->kstype);
228 	if (plugin != NULL && plugin->funclist->DeleteKey != NULL) {
229 		rv = plugin->funclist->DeleteKey(handle, params, key, TRUE);
230 	} else {
231 		rv = KMF_ERR_PLUGIN_NOTFOUND;
232 	}
233 
234 	if (rv == KMF_OK) {
235 		if (key->keylabel != NULL)
236 			free(key->keylabel);
237 
238 		if (key->israw && key->keyp != NULL) {
239 			if (key->keyclass ==  KMF_ASYM_PUB ||
240 			    key->keyclass == KMF_ASYM_PRI) {
241 				KMF_FreeRawKey(key->keyp);
242 				free(key->keyp);
243 			} else if (key->keyclass == KMF_SYMMETRIC) {
244 				KMF_FreeRawSymKey(key->keyp);
245 			}
246 			/* Else we don't know how to free the memory. */
247 		}
248 
249 		(void) memset(key, 0, sizeof (KMF_KEY_HANDLE));
250 	}
251 
252 	return (rv);
253 }
254 
255 KMF_RETURN
256 KMF_SignCertRecord(KMF_HANDLE_T handle, KMF_KEY_HANDLE *kmfprikey,
257 	KMF_X509_CERTIFICATE *CertData, KMF_DATA *signedCert)
258 {
259 	KMF_RETURN ret;
260 	KMF_DATA unsignedCert;
261 
262 	CLEAR_ERROR(handle, ret);
263 	if (ret != KMF_OK)
264 		return (ret);
265 
266 	if (kmfprikey == NULL ||
267 		CertData == NULL || signedCert == NULL)
268 		return (KMF_ERR_BAD_PARAMETER);
269 
270 	ret = KMF_EncodeCertRecord(CertData, &unsignedCert);
271 	if (ret == KMF_OK)
272 		ret = KMF_SignCertWithKey(handle, &unsignedCert, kmfprikey,
273 			signedCert);
274 
275 	KMF_FreeData(&unsignedCert);
276 	return (ret);
277 }
278 
279 KMF_RETURN
280 KMF_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *parms,
281 	KMF_KEY_HANDLE *keys, uint32_t *numkeys)
282 {
283 	KMF_PLUGIN *plugin;
284 	KMF_RETURN ret;
285 
286 	CLEAR_ERROR(handle, ret);
287 	if (ret != KMF_OK)
288 		return (ret);
289 
290 	if (parms == NULL || numkeys == NULL)
291 		return (KMF_ERR_BAD_PARAMETER);
292 
293 	plugin = FindPlugin(handle, parms->kstype);
294 
295 	if (plugin != NULL && plugin->funclist->FindKey != NULL) {
296 		return (plugin->funclist->FindKey(handle, parms,
297 			keys, numkeys));
298 	}
299 
300 	return (KMF_ERR_PLUGIN_NOTFOUND);
301 }
302 
303 KMF_RETURN
304 KMF_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
305 	KMF_RAW_KEY_DATA *rawkey)
306 {
307 	KMF_PLUGIN *plugin;
308 	KMF_RETURN ret;
309 
310 	CLEAR_ERROR(handle, ret);
311 	if (ret != KMF_OK)
312 		return (ret);
313 
314 	if (params == NULL || rawkey == NULL)
315 		return (KMF_ERR_BAD_PARAMETER);
316 
317 	/* Find the private key from the keystore */
318 	plugin = FindPlugin(handle, params->kstype);
319 
320 	if (plugin != NULL && plugin->funclist->StorePrivateKey != NULL) {
321 		return (plugin->funclist->StorePrivateKey(handle,
322 		    params, rawkey));
323 	}
324 	return (KMF_ERR_PLUGIN_NOTFOUND);
325 }
326 
327 KMF_RETURN
328 KMF_CreateSymKey(KMF_HANDLE_T handle, KMF_CREATESYMKEY_PARAMS *params,
329 	KMF_KEY_HANDLE *symkey)
330 {
331 	KMF_PLUGIN *plugin;
332 	KMF_RETURN ret;
333 
334 	CLEAR_ERROR(handle, ret);
335 	if (ret != KMF_OK)
336 		return (ret);
337 
338 	if (params == NULL ||
339 		symkey == NULL)
340 		return (KMF_ERR_BAD_PARAMETER);
341 
342 	plugin = FindPlugin(handle, params->kstype);
343 	if (plugin != NULL && plugin->funclist->CreateSymKey != NULL) {
344 		return (plugin->funclist->CreateSymKey(handle, params,
345 		    symkey));
346 	} else {
347 		return (KMF_ERR_PLUGIN_NOTFOUND);
348 	}
349 }
350 
351 KMF_RETURN
352 KMF_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
353 	KMF_RAW_SYM_KEY *rkey)
354 {
355 	KMF_PLUGIN *plugin;
356 	KMF_RETURN ret;
357 
358 	CLEAR_ERROR(handle, ret);
359 	if (ret != KMF_OK)
360 		return (ret);
361 
362 	if (symkey == NULL || rkey == NULL)
363 		return (KMF_ERR_BAD_PARAMETER);
364 
365 	plugin = FindPlugin(handle, symkey->kstype);
366 	if (plugin != NULL &&
367 	    plugin->funclist->GetSymKeyValue != NULL) {
368 		return (plugin->funclist->GetSymKeyValue(handle,
369 		    symkey, rkey));
370 	} else {
371 		return (KMF_ERR_PLUGIN_NOTFOUND);
372 	}
373 }
374