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 <sys/socket.h>
36 
37 #include <ber_der.h>
38 #include <kmfapiP.h>
39 
40 #include <pem_encode.h>
41 #include <libgen.h>
42 #include <cryptoutil.h>
43 
44 
45 /*
46  *
47  * Name: KMF_SetCSRPubKey
48  *
49  * Description:
50  *   This function converts the specified plugin public key to SPKI form,
51  *   and save it in the KMF_CSR_DATA internal structure
52  *
53  * Parameters:
54  *   KMFkey(input) - pointer to the KMF_KEY_HANDLE structure containing the
55  *		public key generated by the plug-in CreateKeypair
56  *   Csr(input/output) - pointer to a KMF_CSR_DATA structure containing
57  *		SPKI
58  *
59  * Returns:
60  *   A KMF_RETURN value indicating success or specifying a particular
61  *   error condition.
62  *   The value KMF_OK indicates success. All other values represent
63  *   an error condition.
64  *
65  */
66 KMF_RETURN
67 KMF_SetCSRPubKey(KMF_HANDLE_T handle,
68 	KMF_KEY_HANDLE *KMFKey,
69 	KMF_CSR_DATA *Csr)
70 {
71 	KMF_RETURN ret = KMF_OK;
72 	KMF_X509_SPKI *spki_ptr;
73 	KMF_PLUGIN *plugin;
74 	KMF_DATA KeyData = {NULL, 0};
75 
76 	CLEAR_ERROR(handle, ret);
77 	if (ret != KMF_OK)
78 		return (ret);
79 
80 	if (KMFKey == NULL || Csr == NULL) {
81 		return (KMF_ERR_BAD_PARAMETER);
82 	}
83 
84 	/* The keystore must extract the pubkey data */
85 	plugin = FindPlugin(handle, KMFKey->kstype);
86 	if (plugin != NULL && plugin->funclist->EncodePubkeyData != NULL) {
87 		ret = plugin->funclist->EncodePubkeyData(handle,
88 		    KMFKey, &KeyData);
89 	} else {
90 		return (KMF_ERR_PLUGIN_NOTFOUND);
91 	}
92 
93 	spki_ptr = &Csr->csr.subjectPublicKeyInfo;
94 
95 	ret = DerDecodeSPKI(&KeyData, spki_ptr);
96 
97 	KMF_FreeData(&KeyData);
98 
99 	return (ret);
100 }
101 
102 KMF_RETURN
103 KMF_SetCSRVersion(KMF_CSR_DATA *CsrData, uint32_t version)
104 {
105 	if (CsrData == NULL)
106 		return (KMF_ERR_BAD_PARAMETER);
107 
108 	/*
109 	 * From RFC 3280:
110 	 * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
111 	 */
112 	if (version != 0 && version != 1 && version != 2)
113 		return (KMF_ERR_BAD_PARAMETER);
114 	return (set_integer(&CsrData->csr.version, (void *)&version,
115 		sizeof (uint32_t)));
116 }
117 
118 KMF_RETURN
119 KMF_SetCSRSubjectName(KMF_CSR_DATA *CsrData,
120 	KMF_X509_NAME *subject_name_ptr)
121 {
122 	KMF_RETURN rv = KMF_OK;
123 	KMF_X509_NAME *temp_name_ptr = NULL;
124 
125 	if (CsrData != NULL && subject_name_ptr != NULL) {
126 		rv = CopyRDN(subject_name_ptr, &temp_name_ptr);
127 		if (rv == KMF_OK) {
128 			CsrData->csr.subject = *temp_name_ptr;
129 		}
130 	} else {
131 		return (KMF_ERR_BAD_PARAMETER);
132 	}
133 	return (rv);
134 }
135 
136 KMF_RETURN
137 KMF_CreateCSRFile(KMF_DATA *csrdata, KMF_ENCODE_FORMAT format,
138 	char *csrfile)
139 {
140 	KMF_RETURN rv = KMF_OK;
141 	int fd = -1;
142 	KMF_DATA pemdata = {NULL, 0};
143 
144 	if (csrdata == NULL || csrfile == NULL)
145 		return (KMF_ERR_BAD_PARAMETER);
146 
147 	if (format != KMF_FORMAT_PEM && format != KMF_FORMAT_ASN1)
148 		return (KMF_ERR_BAD_PARAMETER);
149 
150 	if (format == KMF_FORMAT_PEM) {
151 		int len;
152 		rv = KMF_Der2Pem(KMF_CSR,
153 			csrdata->Data, csrdata->Length,
154 			&pemdata.Data, &len);
155 		if (rv != KMF_OK)
156 			goto cleanup;
157 		pemdata.Length = (size_t)len;
158 	}
159 
160 	if ((fd = open(csrfile, O_CREAT |O_RDWR, 0644)) == -1) {
161 		rv = KMF_ERR_OPEN_FILE;
162 		goto cleanup;
163 	}
164 
165 	if (format == KMF_FORMAT_PEM) {
166 		if (write(fd, pemdata.Data, pemdata.Length) !=
167 			pemdata.Length) {
168 			rv = KMF_ERR_WRITE_FILE;
169 		}
170 	} else {
171 		if (write(fd, csrdata->Data, csrdata->Length) !=
172 			csrdata->Length) {
173 			rv = KMF_ERR_WRITE_FILE;
174 		}
175 	}
176 
177 cleanup:
178 	if (fd != -1)
179 		(void) close(fd);
180 
181 	KMF_FreeData(&pemdata);
182 
183 	return (rv);
184 }
185 
186 KMF_RETURN
187 KMF_SetCSRExtension(KMF_CSR_DATA *Csr,
188 	KMF_X509_EXTENSION *extn)
189 {
190 	KMF_RETURN ret = KMF_OK;
191 	KMF_X509_EXTENSIONS *exts;
192 
193 	if (Csr == NULL || extn == NULL)
194 		return (KMF_ERR_BAD_PARAMETER);
195 
196 	exts = &Csr->csr.extensions;
197 
198 	ret = add_an_extension(exts, extn);
199 
200 	return (ret);
201 }
202 
203 KMF_RETURN
204 KMF_SetCSRSignatureAlgorithm(KMF_CSR_DATA *CsrData,
205 	KMF_ALGORITHM_INDEX sigAlg)
206 {
207 	KMF_OID	*alg;
208 
209 	if (CsrData == NULL)
210 		return (KMF_ERR_BAD_PARAMETER);
211 
212 	alg = X509_AlgIdToAlgorithmOid(sigAlg);
213 
214 	if (alg != NULL) {
215 		(void) copy_data((KMF_DATA *)
216 			&CsrData->signature.algorithmIdentifier.algorithm,
217 			(KMF_DATA *)alg);
218 		(void) copy_data(
219 		    &CsrData->signature.algorithmIdentifier.parameters,
220 		    &CsrData->csr.subjectPublicKeyInfo.algorithm.parameters);
221 	} else {
222 		return (KMF_ERR_BAD_PARAMETER);
223 	}
224 	return (KMF_OK);
225 }
226 
227 KMF_RETURN
228 KMF_SetCSRSubjectAltName(KMF_CSR_DATA *Csr,
229 	char *altname, int critical,
230 	KMF_GENERALNAMECHOICES alttype)
231 {
232 	KMF_RETURN ret = KMF_OK;
233 
234 	if (Csr == NULL || altname == NULL)
235 		return (KMF_ERR_BAD_PARAMETER);
236 
237 	ret = KMF_SetAltName(&Csr->csr.extensions,
238 		(KMF_OID *)&KMFOID_SubjectAltName, critical, alttype,
239 		altname);
240 
241 	return (ret);
242 }
243 
244 KMF_RETURN
245 KMF_SetCSRKeyUsage(KMF_CSR_DATA *CSRData,
246 	int critical, uint16_t kubits)
247 {
248 	KMF_RETURN ret = KMF_OK;
249 
250 	if (CSRData == NULL)
251 		return (KMF_ERR_BAD_PARAMETER);
252 
253 	ret = set_key_usage_extension(
254 		&CSRData->csr.extensions,
255 		critical, kubits);
256 
257 	return (ret);
258 }
259 
260 /*
261  *
262  * Name: KMF_SignCSR
263  *
264  * Description:
265  *   This function signs a CSR and returns the result as a
266  *   signed, encoded CSR in SignedCsr
267  *
268  * Parameters:
269  *   tbsCsr(input) - pointer to a KMF_DATA structure containing a
270  *		DER encoded TBS CSR data
271  *   Signkey(input) - pointer to the KMF_KEY_HANDLE structure containing
272  *		the private key generated by the plug-in CreateKeypair
273  *   algo(input) - contains algorithm info needed for signing
274  *   SignedCsr(output) - pointer to the KMF_DATA structure containing
275  *		the signed CSR
276  *
277  * Returns:
278  *   A KMF_RETURN value indicating success or specifying a particular
279  *   error condition.
280  *   The value KMF_OK indicates success. All other values represent
281  *   an error condition.
282  *
283  */
284 KMF_RETURN
285 KMF_SignCSR(KMF_HANDLE_T handle,
286 	const KMF_CSR_DATA *tbsCsr,
287 	KMF_KEY_HANDLE	*Signkey,
288 	KMF_DATA	*SignedCsr)
289 {
290 	KMF_RETURN err;
291 	KMF_DATA csrdata = { NULL, 0 };
292 
293 	CLEAR_ERROR(handle, err);
294 	if (err != KMF_OK)
295 		return (err);
296 
297 	if (tbsCsr == NULL ||
298 		Signkey == NULL || SignedCsr == NULL)
299 		return (KMF_ERR_BAD_PARAMETER);
300 
301 	SignedCsr->Data = NULL;
302 	SignedCsr->Length = 0;
303 
304 	err = DerEncodeTbsCsr((KMF_TBS_CSR *)&tbsCsr->csr, &csrdata);
305 	if (err == KMF_OK) {
306 		err = SignCsr(handle, &csrdata, Signkey,
307 			(KMF_X509_ALGORITHM_IDENTIFIER *)
308 				&tbsCsr->signature.algorithmIdentifier,
309 			SignedCsr);
310 	}
311 
312 	if (err != KMF_OK) {
313 		KMF_FreeData(SignedCsr);
314 	}
315 	KMF_FreeData(&csrdata);
316 	return (err);
317 }
318 
319 KMF_RETURN
320 KMF_ImportCRL(KMF_HANDLE_T handle, KMF_IMPORTCRL_PARAMS *params)
321 {
322 	KMF_PLUGIN *plugin;
323 	KMF_RETURN ret;
324 
325 	CLEAR_ERROR(handle, ret);
326 	if (ret != KMF_OK)
327 		return (ret);
328 
329 	if (params == NULL)
330 		return (KMF_ERR_BAD_PARAMETER);
331 
332 	switch (params->kstype) {
333 	case KMF_KEYSTORE_NSS:
334 		plugin = FindPlugin(handle, params->kstype);
335 		break;
336 
337 	case KMF_KEYSTORE_OPENSSL:
338 	case KMF_KEYSTORE_PK11TOKEN: /* PKCS#11 CRL is file-based */
339 		plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
340 		break;
341 	default:
342 		return (KMF_ERR_PLUGIN_NOTFOUND);
343 	}
344 
345 	if (plugin != NULL && plugin->funclist->ImportCRL != NULL) {
346 		return (plugin->funclist->ImportCRL(handle, params));
347 	}
348 	return (KMF_ERR_PLUGIN_NOTFOUND);
349 }
350 
351 KMF_RETURN
352 KMF_DeleteCRL(KMF_HANDLE_T handle, KMF_DELETECRL_PARAMS *params)
353 {
354 	KMF_PLUGIN *plugin;
355 	KMF_RETURN ret;
356 
357 	CLEAR_ERROR(handle, ret);
358 	if (ret != KMF_OK)
359 		return (ret);
360 
361 	if (params == NULL)
362 		return (KMF_ERR_BAD_PARAMETER);
363 
364 	switch (params->kstype) {
365 	case KMF_KEYSTORE_NSS:
366 		plugin = FindPlugin(handle, params->kstype);
367 		break;
368 
369 	case KMF_KEYSTORE_OPENSSL:
370 	case KMF_KEYSTORE_PK11TOKEN: /* PKCS#11 CRL is file-based */
371 		plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
372 		break;
373 	default:
374 		return (KMF_ERR_PLUGIN_NOTFOUND);
375 	}
376 
377 	if (plugin != NULL && plugin->funclist->DeleteCRL != NULL) {
378 		return (plugin->funclist->DeleteCRL(handle, params));
379 	} else {
380 		return (KMF_ERR_PLUGIN_NOTFOUND);
381 	}
382 }
383 
384 KMF_RETURN
385 KMF_ListCRL(KMF_HANDLE_T handle, KMF_LISTCRL_PARAMS *params, char **crldata)
386 {
387 	KMF_PLUGIN *plugin;
388 	KMF_RETURN ret;
389 
390 	CLEAR_ERROR(handle, ret);
391 	if (ret != KMF_OK)
392 		return (ret);
393 
394 	if (params == NULL || crldata == NULL)
395 		return (KMF_ERR_BAD_PARAMETER);
396 
397 	switch (params->kstype) {
398 	case KMF_KEYSTORE_NSS:
399 		plugin = FindPlugin(handle, params->kstype);
400 		break;
401 
402 	case KMF_KEYSTORE_OPENSSL:
403 	case KMF_KEYSTORE_PK11TOKEN: /* PKCS#11 CRL is file-based */
404 		plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
405 		break;
406 	default:
407 		return (KMF_ERR_PLUGIN_NOTFOUND);
408 	}
409 
410 	if (plugin != NULL && plugin->funclist->ListCRL != NULL) {
411 		return (plugin->funclist->ListCRL(handle, params, crldata));
412 	} else {
413 		return (KMF_ERR_PLUGIN_NOTFOUND);
414 	}
415 }
416 
417 KMF_RETURN
418 KMF_FindCRL(KMF_HANDLE_T handle, KMF_FINDCRL_PARAMS *params,
419 	char **CRLNameList, int *CRLCount)
420 {
421 	KMF_PLUGIN *plugin;
422 	KMF_RETURN ret;
423 
424 	CLEAR_ERROR(handle, ret);
425 	if (ret != KMF_OK)
426 		return (ret);
427 
428 	if (params == NULL ||
429 		CRLCount == NULL)
430 		return (KMF_ERR_BAD_PARAMETER);
431 
432 	plugin = FindPlugin(handle, params->kstype);
433 	if (plugin != NULL && plugin->funclist->FindCRL != NULL) {
434 		return (plugin->funclist->FindCRL(handle, params,
435 			CRLNameList, CRLCount));
436 	} else {
437 		return (KMF_ERR_PLUGIN_NOTFOUND);
438 	}
439 }
440 
441 KMF_RETURN
442 KMF_FindCertInCRL(KMF_HANDLE_T handle, KMF_FINDCERTINCRL_PARAMS *params)
443 {
444 	KMF_PLUGIN *plugin;
445 	KMF_RETURN ret;
446 
447 	CLEAR_ERROR(handle, ret);
448 	if (ret != KMF_OK)
449 		return (ret);
450 
451 	if (params == NULL)
452 		return (KMF_ERR_BAD_PARAMETER);
453 
454 	switch (params->kstype) {
455 	case KMF_KEYSTORE_NSS:
456 		plugin = FindPlugin(handle, params->kstype);
457 		break;
458 
459 	case KMF_KEYSTORE_OPENSSL:
460 	case KMF_KEYSTORE_PK11TOKEN: /* PKCS#11 CRL is file-based */
461 		plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
462 		break;
463 	default:
464 		return (KMF_ERR_PLUGIN_NOTFOUND);
465 	}
466 
467 	if (plugin != NULL && plugin->funclist->FindCertInCRL != NULL) {
468 		return (plugin->funclist->FindCertInCRL(handle, params));
469 	} else {
470 		return (KMF_ERR_PLUGIN_NOTFOUND);
471 	}
472 }
473 
474 KMF_RETURN
475 KMF_VerifyCRLFile(KMF_HANDLE_T handle,
476 	KMF_VERIFYCRL_PARAMS *params)
477 {
478 	KMF_PLUGIN *plugin;
479 	KMF_RETURN (*verifyCRLFile)(KMF_HANDLE_T,
480 		KMF_VERIFYCRL_PARAMS *);
481 	KMF_RETURN ret;
482 
483 	CLEAR_ERROR(handle, ret);
484 	if (ret != KMF_OK)
485 		return (ret);
486 
487 	if (params == NULL)
488 		return (KMF_ERR_BAD_PARAMETER);
489 
490 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
491 	if (plugin == NULL || plugin->dldesc == NULL) {
492 		return (KMF_ERR_PLUGIN_NOTFOUND);
493 	}
494 
495 	verifyCRLFile = (KMF_RETURN(*)())dlsym(plugin->dldesc,
496 	    "OpenSSL_VerifyCRLFile");
497 
498 	if (verifyCRLFile == NULL) {
499 		return (KMF_ERR_FUNCTION_NOT_FOUND);
500 	}
501 
502 	return (verifyCRLFile(handle, params));
503 }
504 
505 KMF_RETURN
506 KMF_CheckCRLDate(KMF_HANDLE_T handle, KMF_CHECKCRLDATE_PARAMS *params)
507 {
508 	KMF_PLUGIN *plugin;
509 	KMF_RETURN (*checkCRLDate)(void *,
510 	    KMF_CHECKCRLDATE_PARAMS *params);
511 	KMF_RETURN ret;
512 
513 	CLEAR_ERROR(handle, ret);
514 	if (ret != KMF_OK)
515 		return (ret);
516 
517 	if (params == NULL)
518 		return (KMF_ERR_BAD_PARAMETER);
519 
520 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
521 	if (plugin == NULL || plugin->dldesc == NULL) {
522 		return (KMF_ERR_PLUGIN_NOTFOUND);
523 	}
524 
525 	checkCRLDate = (KMF_RETURN(*)())dlsym(plugin->dldesc,
526 	    "OpenSSL_CheckCRLDate");
527 
528 	if (checkCRLDate == NULL) {
529 		return (KMF_ERR_FUNCTION_NOT_FOUND);
530 	}
531 
532 	return (checkCRLDate(handle, params));
533 
534 }
535 
536 KMF_RETURN
537 KMF_IsCRLFile(KMF_HANDLE_T handle, char *filename, KMF_ENCODE_FORMAT *pformat)
538 {
539 	KMF_PLUGIN *plugin;
540 	KMF_RETURN (*IsCRLFileFn)(void *, char *, KMF_ENCODE_FORMAT *);
541 	KMF_RETURN ret;
542 
543 	CLEAR_ERROR(handle, ret);
544 	if (ret != KMF_OK)
545 		return (ret);
546 
547 	if (filename  == NULL || pformat == NULL) {
548 		return (KMF_ERR_BAD_PARAMETER);
549 	}
550 
551 	/*
552 	 * This framework function is actually implemented in the openssl
553 	 * plugin library, so we find the function address and call it.
554 	 */
555 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
556 	if (plugin == NULL || plugin->dldesc == NULL) {
557 		return (KMF_ERR_PLUGIN_NOTFOUND);
558 	}
559 
560 	IsCRLFileFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
561 	    "OpenSSL_IsCRLFile");
562 	if (IsCRLFileFn == NULL) {
563 		return (KMF_ERR_FUNCTION_NOT_FOUND);
564 	}
565 
566 	return (IsCRLFileFn(handle, filename, pformat));
567 }
568