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 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
22 * Use is subject to license terms.
23 */
24
25#include <stdio.h>
26#include <link.h>
27#include <fcntl.h>
28#include <ctype.h>
29#include <sys/param.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <sys/socket.h>
33
34#include <ber_der.h>
35#include <kmfapiP.h>
36
37#include <pem_encode.h>
38#include <libgen.h>
39#include <cryptoutil.h>
40
41static KMF_RETURN
42setup_crl_call(KMF_HANDLE_T, int, KMF_ATTRIBUTE *, KMF_PLUGIN **);
43
44/*
45 *
46 * Name: kmf_set_csr_pubkey
47 *
48 * Description:
49 *   This function converts the specified plugin public key to SPKI form,
50 *   and save it in the KMF_CSR_DATA internal structure
51 *
52 * Parameters:
53 *   KMFkey(input) - pointer to the KMF_KEY_HANDLE structure containing the
54 *		public key generated by the plug-in CreateKeypair
55 *   Csr(input/output) - pointer to a KMF_CSR_DATA structure containing
56 *		SPKI
57 *
58 * Returns:
59 *   A KMF_RETURN value indicating success or specifying a particular
60 *   error condition.
61 *   The value KMF_OK indicates success. All other values represent
62 *   an error condition.
63 *
64 */
65KMF_RETURN
66kmf_set_csr_pubkey(KMF_HANDLE_T handle,
67	KMF_KEY_HANDLE *KMFKey,
68	KMF_CSR_DATA *Csr)
69{
70	KMF_RETURN ret;
71	KMF_X509_SPKI *spki_ptr;
72	KMF_PLUGIN *plugin;
73	KMF_DATA KeyData = { 0, NULL };
74
75	CLEAR_ERROR(handle, ret);
76	if (ret != KMF_OK)
77		return (ret);
78
79	if (KMFKey == NULL || Csr == NULL) {
80		return (KMF_ERR_BAD_PARAMETER);
81	}
82
83	/* The keystore must extract the pubkey data */
84	plugin = FindPlugin(handle, KMFKey->kstype);
85	if (plugin != NULL && plugin->funclist->EncodePubkeyData != NULL) {
86		ret = plugin->funclist->EncodePubkeyData(handle,
87		    KMFKey, &KeyData);
88	} else {
89		return (KMF_ERR_PLUGIN_NOTFOUND);
90	}
91
92	spki_ptr = &Csr->csr.subjectPublicKeyInfo;
93
94	ret = DerDecodeSPKI(&KeyData, spki_ptr);
95
96	kmf_free_data(&KeyData);
97
98	return (ret);
99}
100
101KMF_RETURN
102kmf_set_csr_version(KMF_CSR_DATA *CsrData, uint32_t version)
103{
104	if (CsrData == NULL)
105		return (KMF_ERR_BAD_PARAMETER);
106
107	/*
108	 * From RFC 3280:
109	 * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
110	 */
111	if (version != 0 && version != 1 && version != 2)
112		return (KMF_ERR_BAD_PARAMETER);
113	return (set_integer(&CsrData->csr.version, (void *)&version,
114	    sizeof (uint32_t)));
115}
116
117KMF_RETURN
118kmf_set_csr_subject(KMF_CSR_DATA *CsrData,
119	KMF_X509_NAME *subject_name_ptr)
120{
121	KMF_RETURN rv = KMF_OK;
122	KMF_X509_NAME *temp_name_ptr = NULL;
123
124	if (CsrData != NULL && subject_name_ptr != NULL) {
125		rv = CopyRDN(subject_name_ptr, &temp_name_ptr);
126		if (rv == KMF_OK) {
127			CsrData->csr.subject = *temp_name_ptr;
128		}
129	} else {
130		return (KMF_ERR_BAD_PARAMETER);
131	}
132	return (rv);
133}
134KMF_RETURN
135kmf_create_csr_file(KMF_DATA *csrdata, KMF_ENCODE_FORMAT format,
136	char *csrfile)
137{
138	KMF_RETURN rv = KMF_OK;
139	int fd = -1;
140	KMF_DATA pemdata = { 0, NULL };
141
142	if (csrdata == NULL || csrfile == NULL)
143		return (KMF_ERR_BAD_PARAMETER);
144
145	if (format != KMF_FORMAT_PEM && format != KMF_FORMAT_ASN1)
146		return (KMF_ERR_BAD_PARAMETER);
147
148	if (format == KMF_FORMAT_PEM) {
149		int len;
150		rv = kmf_der_to_pem(KMF_CSR,
151		    csrdata->Data, csrdata->Length,
152		    &pemdata.Data, &len);
153		if (rv != KMF_OK)
154			goto cleanup;
155		pemdata.Length = (size_t)len;
156	}
157
158	if ((fd = open(csrfile, O_CREAT |O_RDWR, 0644)) == -1) {
159		rv = KMF_ERR_OPEN_FILE;
160		goto cleanup;
161	}
162
163	if (format == KMF_FORMAT_PEM) {
164		if (write(fd, pemdata.Data, pemdata.Length) !=
165		    pemdata.Length) {
166			rv = KMF_ERR_WRITE_FILE;
167		}
168	} else {
169		if (write(fd, csrdata->Data, csrdata->Length) !=
170		    csrdata->Length) {
171			rv = KMF_ERR_WRITE_FILE;
172		}
173	}
174
175cleanup:
176	if (fd != -1)
177		(void) close(fd);
178
179	kmf_free_data(&pemdata);
180
181	return (rv);
182}
183
184KMF_RETURN
185kmf_set_csr_extn(KMF_CSR_DATA *Csr, KMF_X509_EXTENSION *extn)
186{
187	KMF_RETURN ret = KMF_OK;
188	KMF_X509_EXTENSIONS *exts;
189
190	if (Csr == NULL || extn == NULL)
191		return (KMF_ERR_BAD_PARAMETER);
192
193	exts = &Csr->csr.extensions;
194
195	ret = add_an_extension(exts, extn);
196
197	return (ret);
198}
199
200KMF_RETURN
201kmf_set_csr_sig_alg(KMF_CSR_DATA *CsrData,
202	KMF_ALGORITHM_INDEX sigAlg)
203{
204	KMF_OID	*alg;
205
206	if (CsrData == NULL)
207		return (KMF_ERR_BAD_PARAMETER);
208
209	alg = x509_algid_to_algoid(sigAlg);
210
211	if (alg != NULL) {
212		(void) copy_data((KMF_DATA *)
213		    &CsrData->signature.algorithmIdentifier.algorithm,
214		    (KMF_DATA *)alg);
215		(void) copy_data(
216		    &CsrData->signature.algorithmIdentifier.parameters,
217		    &CsrData->csr.subjectPublicKeyInfo.algorithm.parameters);
218	} else {
219		return (KMF_ERR_BAD_PARAMETER);
220	}
221	return (KMF_OK);
222}
223
224KMF_RETURN
225kmf_set_csr_subject_altname(KMF_CSR_DATA *Csr,
226	char *altname, int critical,
227	KMF_GENERALNAMECHOICES alttype)
228{
229	KMF_RETURN ret = KMF_OK;
230
231	if (Csr == NULL || altname == NULL)
232		return (KMF_ERR_BAD_PARAMETER);
233
234	ret = kmf_set_altname(&Csr->csr.extensions,
235	    (KMF_OID *)&KMFOID_SubjectAltName, critical, alttype,
236	    altname);
237
238	return (ret);
239}
240
241KMF_RETURN
242kmf_set_csr_ku(KMF_CSR_DATA *CSRData,
243	int critical, uint16_t kubits)
244{
245	KMF_RETURN ret = KMF_OK;
246
247	if (CSRData == NULL)
248		return (KMF_ERR_BAD_PARAMETER);
249
250	ret = set_key_usage_extension(
251	    &CSRData->csr.extensions, critical, kubits);
252
253	return (ret);
254}
255
256KMF_RETURN
257kmf_add_csr_eku(KMF_CSR_DATA *CSRData, KMF_OID *ekuOID,
258	int critical)
259{
260	KMF_RETURN ret = KMF_OK;
261	KMF_X509_EXTENSION *foundextn;
262	KMF_X509_EXTENSION newextn;
263	BerElement *asn1 = NULL;
264	BerValue *extdata = NULL;
265	char *olddata = NULL;
266	size_t oldsize = 0;
267	KMF_X509EXT_EKU ekudata;
268
269	if (CSRData == NULL || ekuOID == NULL)
270		return (KMF_ERR_BAD_PARAMETER);
271
272	(void) memset(&ekudata, 0, sizeof (KMF_X509EXT_EKU));
273	(void) memset(&newextn, 0, sizeof (newextn));
274
275	foundextn = FindExtn(&CSRData->csr.extensions,
276	    (KMF_OID *)&KMFOID_ExtendedKeyUsage);
277	if (foundextn != NULL) {
278		ret = GetSequenceContents((char *)foundextn->BERvalue.Data,
279		    foundextn->BERvalue.Length, &olddata, &oldsize);
280		if (ret != KMF_OK)
281			goto out;
282
283		/*
284		 * If the EKU is already in the cert, then just return OK.
285		 */
286		ret = parse_eku_data(&foundextn->BERvalue, &ekudata);
287		if (ret == KMF_OK) {
288			if (is_eku_present(&ekudata, ekuOID)) {
289				goto out;
290			}
291		}
292	}
293	if ((asn1 = kmfder_alloc()) == NULL)
294		return (KMF_ERR_MEMORY);
295
296	if (kmfber_printf(asn1, "{") == -1) {
297		ret = KMF_ERR_ENCODING;
298		goto out;
299	}
300
301	/* Write the old extension data first */
302	if (olddata != NULL && oldsize > 0) {
303		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
304			ret = KMF_ERR_ENCODING;
305			goto out;
306		}
307	}
308
309	/* Append this EKU OID and close the sequence */
310	if (kmfber_printf(asn1, "D}", ekuOID) == -1) {
311		ret = KMF_ERR_ENCODING;
312		goto out;
313	}
314
315	if (kmfber_flatten(asn1, &extdata) == -1) {
316		ret = KMF_ERR_ENCODING;
317		goto out;
318	}
319
320	/*
321	 * If we are just adding to an existing list of EKU OIDs,
322	 * just replace the BER data associated with the found extension.
323	 */
324	if (foundextn != NULL) {
325		free(foundextn->BERvalue.Data);
326		foundextn->critical = critical;
327		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
328		foundextn->BERvalue.Length = extdata->bv_len;
329	} else {
330		ret = copy_data(&newextn.extnId,
331		    (KMF_DATA *)&KMFOID_ExtendedKeyUsage);
332		if (ret != KMF_OK)
333			goto out;
334		newextn.critical = critical;
335		newextn.format = KMF_X509_DATAFORMAT_ENCODED;
336		newextn.BERvalue.Data = (uchar_t *)extdata->bv_val;
337		newextn.BERvalue.Length = extdata->bv_len;
338		ret = kmf_set_csr_extn(CSRData, &newextn);
339		if (ret != KMF_OK)
340			free(newextn.BERvalue.Data);
341	}
342
343out:
344	kmf_free_eku(&ekudata);
345	if (extdata != NULL)
346		free(extdata);
347
348	if (olddata != NULL)
349		free(olddata);
350
351	if (asn1 != NULL)
352		kmfber_free(asn1, 1);
353
354	if (ret != KMF_OK)
355		kmf_free_data(&newextn.extnId);
356
357	return (ret);
358}
359
360static KMF_RETURN
361sign_csr(KMF_HANDLE_T handle,
362	const KMF_DATA *SubjectCsr,
363	KMF_KEY_HANDLE	*Signkey,
364	KMF_X509_ALGORITHM_IDENTIFIER *algo,
365	KMF_DATA	*SignedCsr)
366{
367	KMF_CSR_DATA	subj_csr;
368	KMF_TBS_CSR	*tbs_csr = NULL;
369	KMF_DATA	signed_data = { 0, NULL };
370	KMF_RETURN	ret = KMF_OK;
371	KMF_ATTRIBUTE	attlist[5];
372	KMF_ALGORITHM_INDEX algid;
373	int i = 0;
374
375	if (!SignedCsr)
376		return (KMF_ERR_BAD_PARAMETER);
377
378	SignedCsr->Length = 0;
379	SignedCsr->Data = NULL;
380
381	if (!SubjectCsr)
382		return (KMF_ERR_BAD_PARAMETER);
383
384	if (!SubjectCsr->Data || !SubjectCsr->Length)
385		return (KMF_ERR_BAD_PARAMETER);
386
387	(void) memset(&subj_csr, 0, sizeof (subj_csr));
388	/* Estimate the signed data length generously */
389	signed_data.Length = SubjectCsr->Length*2;
390	signed_data.Data = calloc(1, signed_data.Length);
391	if (!signed_data.Data) {
392		ret = KMF_ERR_MEMORY;
393		goto cleanup;
394	}
395
396	kmf_set_attr_at_index(attlist, i++,
397	    KMF_KEYSTORE_TYPE_ATTR, &Signkey->kstype,
398	    sizeof (Signkey->kstype));
399
400	kmf_set_attr_at_index(attlist, i++,
401	    KMF_KEY_HANDLE_ATTR, Signkey, sizeof (KMF_KEY_HANDLE));
402
403	kmf_set_attr_at_index(attlist, i++, KMF_OID_ATTR, &algo->algorithm,
404	    sizeof (KMF_OID));
405
406	kmf_set_attr_at_index(attlist, i++, KMF_DATA_ATTR,
407	    (KMF_DATA *)SubjectCsr, sizeof (KMF_DATA));
408
409	kmf_set_attr_at_index(attlist, i++, KMF_OUT_DATA_ATTR,
410	    &signed_data, sizeof (KMF_DATA));
411
412	ret = kmf_sign_data(handle, i, attlist);
413	if (KMF_OK != ret)
414		goto cleanup;
415	/*
416	 * If we got here OK, decode into a structure and then re-encode
417	 * the complete CSR.
418	 */
419	ret = DerDecodeTbsCsr(SubjectCsr, &tbs_csr);
420	if (ret)
421		goto cleanup;
422
423	(void) memcpy(&subj_csr.csr, tbs_csr, sizeof (KMF_TBS_CSR));
424
425	ret = copy_algoid(&subj_csr.signature.algorithmIdentifier, algo);
426	if (ret)
427		goto cleanup;
428
429	algid = x509_algoid_to_algid(&algo->algorithm);
430	if (algid == KMF_ALGID_SHA1WithDSA ||
431	    algid == KMF_ALGID_SHA256WithDSA ||
432	    algid == KMF_ALGID_SHA1WithECDSA ||
433	    algid == KMF_ALGID_SHA256WithECDSA ||
434	    algid == KMF_ALGID_SHA384WithECDSA ||
435	    algid == KMF_ALGID_SHA512WithECDSA) {
436		/*
437		 * For DSA and ECDSA, we must encode the
438		 * signature correctly.
439		 */
440		KMF_DATA signature;
441
442		ret = DerEncodeDSASignature(&signed_data, &signature);
443		kmf_free_data(&signed_data);
444
445		if (ret != KMF_OK)
446			goto cleanup;
447
448		subj_csr.signature.encrypted = signature;
449	} else {
450		subj_csr.signature.encrypted = signed_data;
451	}
452
453	/* Now, re-encode the CSR with the new signature */
454	ret = DerEncodeSignedCsr(&subj_csr, SignedCsr);
455	if (ret != KMF_OK) {
456		kmf_free_data(SignedCsr);
457		goto cleanup;
458	}
459
460	/* Cleanup & return */
461cleanup:
462	free(tbs_csr);
463
464	kmf_free_tbs_csr(&subj_csr.csr);
465
466	kmf_free_algoid(&subj_csr.signature.algorithmIdentifier);
467	kmf_free_data(&signed_data);
468
469	return (ret);
470}
471
472/*
473 *
474 * Name: kmf_sign_csr
475 *
476 * Description:
477 *   This function signs a CSR and returns the result as a
478 *   signed, encoded CSR in SignedCsr
479 *
480 * Parameters:
481 *   tbsCsr(input) - pointer to a KMF_DATA structure containing a
482 *		DER encoded TBS CSR data
483 *   Signkey(input) - pointer to the KMF_KEY_HANDLE structure containing
484 *		the private key generated by the plug-in CreateKeypair
485 *   algo(input) - contains algorithm info needed for signing
486 *   SignedCsr(output) - pointer to the KMF_DATA structure containing
487 *		the signed CSR
488 *
489 * Returns:
490 *   A KMF_RETURN value indicating success or specifying a particular
491 *   error condition.
492 *   The value KMF_OK indicates success. All other values represent
493 *   an error condition.
494 *
495 */
496KMF_RETURN
497kmf_sign_csr(KMF_HANDLE_T handle,
498	const KMF_CSR_DATA *tbsCsr,
499	KMF_KEY_HANDLE	*Signkey,
500	KMF_DATA	*SignedCsr)
501{
502	KMF_RETURN err;
503	KMF_DATA csrdata = { 0, NULL };
504
505	CLEAR_ERROR(handle, err);
506	if (err != KMF_OK)
507		return (err);
508
509	if (tbsCsr == NULL || Signkey == NULL || SignedCsr == NULL)
510		return (KMF_ERR_BAD_PARAMETER);
511
512	SignedCsr->Data = NULL;
513	SignedCsr->Length = 0;
514
515	err = DerEncodeTbsCsr((KMF_TBS_CSR *)&tbsCsr->csr, &csrdata);
516	if (err == KMF_OK) {
517		err = sign_csr(handle, &csrdata, Signkey,
518		    (KMF_X509_ALGORITHM_IDENTIFIER *)
519		    &tbsCsr->signature.algorithmIdentifier,
520		    SignedCsr);
521	}
522
523	if (err != KMF_OK) {
524		kmf_free_data(SignedCsr);
525	}
526	kmf_free_data(&csrdata);
527	return (err);
528}
529
530/*
531 * kmf_decode_csr
532 *
533 * Description:
534 *   This function decodes raw CSR data and fills in the KMF_CSR_DATA
535 *   record.
536 *
537 * Inputs:
538 *	KMF_HANDLE_T handle
539 *	KMF_DATA *rawcsr
540 *	KMF_CSR_DATA *csrdata;
541 */
542KMF_RETURN
543kmf_decode_csr(KMF_HANDLE_T handle, KMF_DATA *rawcsr, KMF_CSR_DATA *csrdata)
544{
545	KMF_RETURN rv;
546	KMF_CSR_DATA *cdata = NULL;
547
548	if (handle == NULL || rawcsr == NULL || csrdata == NULL)
549		return (KMF_ERR_BAD_PARAMETER);
550
551	rv = DerDecodeSignedCsr(rawcsr, &cdata);
552	if (rv != KMF_OK)
553		return (rv);
554
555	(void) memcpy(csrdata, cdata, sizeof (KMF_CSR_DATA));
556
557	free(cdata);
558	return (rv);
559}
560
561KMF_RETURN
562kmf_verify_csr(KMF_HANDLE_T handle, int numattr,
563	KMF_ATTRIBUTE *attrlist)
564{
565	KMF_RETURN rv = KMF_OK;
566	KMF_CSR_DATA *csrdata = NULL;
567	KMF_ALGORITHM_INDEX algid;
568	KMF_X509_ALGORITHM_IDENTIFIER *x509alg;
569	KMF_DATA rawcsr;
570
571	KMF_ATTRIBUTE_TESTER required_attrs[] = {
572	    {KMF_CSR_DATA_ATTR, FALSE, sizeof (KMF_CSR_DATA),
573	    sizeof (KMF_CSR_DATA)},
574	};
575
576	int num_req_attrs = sizeof (required_attrs) /
577	    sizeof (KMF_ATTRIBUTE_TESTER);
578
579	if (handle == NULL)
580		return (KMF_ERR_BAD_PARAMETER);
581
582	CLEAR_ERROR(handle, rv);
583
584	rv = test_attributes(num_req_attrs, required_attrs,
585	    0, NULL, numattr, attrlist);
586	if (rv != KMF_OK)
587		return (rv);
588
589	csrdata = kmf_get_attr_ptr(KMF_CSR_DATA_ATTR, attrlist, numattr);
590	if (csrdata == NULL)
591		return (KMF_ERR_BAD_PARAMETER);
592
593	rv = DerEncodeTbsCsr(&csrdata->csr, &rawcsr);
594	if (rv != KMF_OK)
595		return (rv);
596
597	x509alg = &csrdata->signature.algorithmIdentifier;
598	algid = x509_algoid_to_algid(&x509alg->algorithm);
599	if (algid == KMF_ALGID_SHA1WithDSA ||
600	    algid == KMF_ALGID_SHA256WithDSA) {
601		/* Decode the DSA signature before verifying it */
602		KMF_DATA signature;
603		rv = DerDecodeDSASignature(&csrdata->signature.encrypted,
604		    &signature);
605		if (rv != KMF_OK)
606			goto end;
607
608		rv = PKCS_VerifyData(handle, algid,
609		    &csrdata->csr.subjectPublicKeyInfo,
610		    &rawcsr, &signature);
611
612		kmf_free_data(&signature);
613	} else if (algid == KMF_ALGID_SHA1WithECDSA ||
614	    algid == KMF_ALGID_SHA256WithECDSA ||
615	    algid == KMF_ALGID_SHA384WithECDSA ||
616	    algid == KMF_ALGID_SHA512WithECDSA) {
617		KMF_DATA signature;
618		rv = DerDecodeECDSASignature(&csrdata->signature.encrypted,
619		    &signature);
620		if (rv != KMF_OK)
621			goto end;
622
623		rv = PKCS_VerifyData(handle, algid,
624		    &csrdata->csr.subjectPublicKeyInfo,
625		    &rawcsr, &signature);
626
627		kmf_free_data(&signature);
628	} else {
629		rv = PKCS_VerifyData(handle, algid,
630		    &csrdata->csr.subjectPublicKeyInfo,
631		    &rawcsr,
632		    &csrdata->signature.encrypted);
633	}
634
635end:
636	kmf_free_data(&rawcsr);
637	return (rv);
638}
639
640static KMF_RETURN
641setup_crl_call(KMF_HANDLE_T handle, int numattr,
642	KMF_ATTRIBUTE *attrlist, KMF_PLUGIN **plugin)
643{
644	KMF_RETURN ret;
645	KMF_KEYSTORE_TYPE kstype;
646	uint32_t len = sizeof (kstype);
647
648	KMF_ATTRIBUTE_TESTER required_attrs[] = {
649	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)}
650	};
651
652	int num_req_attrs = sizeof (required_attrs) /
653	    sizeof (KMF_ATTRIBUTE_TESTER);
654
655	if (handle == NULL || plugin == NULL)
656		return (KMF_ERR_BAD_PARAMETER);
657
658	CLEAR_ERROR(handle, ret);
659
660	ret = test_attributes(num_req_attrs, required_attrs,
661	    0, NULL, numattr, attrlist);
662	if (ret != KMF_OK)
663		return (ret);
664
665	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
666	    &kstype, &len);
667	if (ret != KMF_OK)
668		return (ret);
669
670	switch (kstype) {
671	case KMF_KEYSTORE_NSS:
672		*plugin = FindPlugin(handle, kstype);
673		break;
674
675	case KMF_KEYSTORE_OPENSSL:
676	case KMF_KEYSTORE_PK11TOKEN: /* PKCS#11 CRL is file-based */
677		*plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
678		break;
679	default:
680		return (KMF_ERR_PLUGIN_NOTFOUND);
681	}
682	return (KMF_OK);
683}
684
685KMF_RETURN
686kmf_import_crl(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
687{
688	KMF_RETURN ret;
689	KMF_PLUGIN *plugin;
690
691	ret = setup_crl_call(handle, numattr, attrlist, &plugin);
692	if (ret != KMF_OK)
693		return (ret);
694
695	if (plugin == NULL)
696		return (KMF_ERR_PLUGIN_NOTFOUND);
697	else if (plugin->funclist->ImportCRL != NULL)
698		return (plugin->funclist->ImportCRL(handle, numattr, attrlist));
699
700	return (KMF_ERR_FUNCTION_NOT_FOUND);
701}
702
703KMF_RETURN
704kmf_delete_crl(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
705{
706	KMF_RETURN ret;
707	KMF_PLUGIN *plugin;
708
709	ret = setup_crl_call(handle, numattr, attrlist, &plugin);
710	if (ret != KMF_OK)
711		return (ret);
712
713	if (plugin == NULL)
714		return (KMF_ERR_PLUGIN_NOTFOUND);
715	else if (plugin->funclist->DeleteCRL != NULL)
716		return (plugin->funclist->DeleteCRL(handle, numattr, attrlist));
717
718	return (KMF_ERR_FUNCTION_NOT_FOUND);
719}
720
721KMF_RETURN
722kmf_list_crl(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
723{
724	KMF_PLUGIN *plugin;
725	KMF_RETURN ret;
726
727	ret = setup_crl_call(handle, numattr, attrlist, &plugin);
728	if (ret != KMF_OK)
729		return (ret);
730
731	if (plugin == NULL)
732		return (KMF_ERR_PLUGIN_NOTFOUND);
733	else if (plugin->funclist->ListCRL != NULL)
734		return (plugin->funclist->ListCRL(handle, numattr, attrlist));
735	return (KMF_ERR_FUNCTION_NOT_FOUND);
736}
737
738KMF_RETURN
739kmf_find_crl(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
740{
741	KMF_PLUGIN *plugin;
742	KMF_RETURN ret;
743	KMF_KEYSTORE_TYPE kstype;
744	uint32_t len = sizeof (kstype);
745
746	KMF_ATTRIBUTE_TESTER required_attrs[] = {
747	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1,
748	    sizeof (KMF_KEYSTORE_TYPE)},
749	    {KMF_CRL_COUNT_ATTR, FALSE,
750	    sizeof (char *), sizeof (char *)}
751	};
752
753	int num_req_attrs = sizeof (required_attrs) /
754	    sizeof (KMF_ATTRIBUTE_TESTER);
755	if (handle == NULL)
756		return (KMF_ERR_BAD_PARAMETER);
757
758	CLEAR_ERROR(handle, ret);
759
760	ret = test_attributes(num_req_attrs, required_attrs,
761	    0, NULL, numattr, attrlist);
762	if (ret != KMF_OK)
763		return (ret);
764
765	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
766	    &kstype, &len);
767	if (ret != KMF_OK)
768		return (ret);
769
770	switch (kstype) {
771	case KMF_KEYSTORE_NSS:
772		plugin = FindPlugin(handle, kstype);
773		break;
774	case KMF_KEYSTORE_OPENSSL:
775	case KMF_KEYSTORE_PK11TOKEN:
776		return (KMF_ERR_FUNCTION_NOT_FOUND);
777	default:
778		/*
779		 * FindCRL is only implemented for NSS. PKCS#11
780		 * and file-based keystores just store in a file
781		 * and don't need a "Find" function.
782		 */
783		return (KMF_ERR_PLUGIN_NOTFOUND);
784	}
785
786	if (plugin == NULL)
787		return (KMF_ERR_PLUGIN_NOTFOUND);
788	else if (plugin->funclist->FindCRL != NULL) {
789		return (plugin->funclist->FindCRL(handle, numattr,
790		    attrlist));
791	}
792	return (KMF_ERR_FUNCTION_NOT_FOUND);
793}
794
795KMF_RETURN
796kmf_find_cert_in_crl(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
797{
798	KMF_RETURN ret;
799	KMF_PLUGIN *plugin;
800
801	ret = setup_crl_call(handle, numattr, attrlist, &plugin);
802	if (ret != KMF_OK)
803		return (ret);
804
805	if (plugin == NULL)
806		return (KMF_ERR_PLUGIN_NOTFOUND);
807	else if (plugin->funclist->FindCertInCRL != NULL)
808		return (plugin->funclist->FindCertInCRL(handle, numattr,
809		    attrlist));
810
811	return (KMF_ERR_FUNCTION_NOT_FOUND);
812}
813
814KMF_RETURN
815kmf_verify_crl_file(KMF_HANDLE_T handle, char *crlfile, KMF_DATA *tacert)
816{
817	KMF_PLUGIN *plugin;
818	KMF_RETURN (*verifyCRLFile)(KMF_HANDLE_T, char *, KMF_DATA *);
819
820	if (handle == NULL)
821		return (KMF_ERR_BAD_PARAMETER);
822
823	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
824	if (plugin == NULL || plugin->dldesc == NULL) {
825		return (KMF_ERR_PLUGIN_NOTFOUND);
826	}
827
828	verifyCRLFile = (KMF_RETURN(*)())dlsym(plugin->dldesc,
829	    "OpenSSL_VerifyCRLFile");
830
831	if (verifyCRLFile == NULL) {
832		return (KMF_ERR_FUNCTION_NOT_FOUND);
833	}
834
835	return (verifyCRLFile(handle, crlfile, tacert));
836}
837
838KMF_RETURN
839kmf_check_crl_date(KMF_HANDLE_T handle, char *crlname)
840{
841	KMF_PLUGIN *plugin;
842	KMF_RETURN (*checkCRLDate)(void *, char *);
843	KMF_RETURN ret = KMF_OK;
844
845	if (handle == NULL)
846		return (KMF_ERR_BAD_PARAMETER);
847
848	CLEAR_ERROR(handle, ret);
849	if (ret != KMF_OK)
850		return (ret);
851
852	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
853	if (plugin == NULL || plugin->dldesc == NULL) {
854		return (KMF_ERR_PLUGIN_NOTFOUND);
855	}
856
857	checkCRLDate = (KMF_RETURN(*)())dlsym(plugin->dldesc,
858	    "OpenSSL_CheckCRLDate");
859
860	if (checkCRLDate == NULL) {
861		return (KMF_ERR_FUNCTION_NOT_FOUND);
862	}
863
864	return (checkCRLDate(handle, crlname));
865}
866
867KMF_RETURN
868kmf_is_crl_file(KMF_HANDLE_T handle, char *filename, KMF_ENCODE_FORMAT *pformat)
869{
870	KMF_PLUGIN *plugin;
871	KMF_RETURN (*IsCRLFileFn)(void *, char *, KMF_ENCODE_FORMAT *);
872	KMF_RETURN ret = KMF_OK;
873
874	CLEAR_ERROR(handle, ret);
875	if (ret != KMF_OK)
876		return (ret);
877
878	if (filename  == NULL || pformat == NULL) {
879		return (KMF_ERR_BAD_PARAMETER);
880	}
881
882	/*
883	 * This framework function is actually implemented in the openssl
884	 * plugin library, so we find the function address and call it.
885	 */
886	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
887	if (plugin == NULL || plugin->dldesc == NULL) {
888		return (KMF_ERR_PLUGIN_NOTFOUND);
889	}
890
891	IsCRLFileFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
892	    "OpenSSL_IsCRLFile");
893	if (IsCRLFileFn == NULL) {
894		return (KMF_ERR_FUNCTION_NOT_FOUND);
895	}
896
897	return (IsCRLFileFn(handle, filename, pformat));
898}
899