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 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <limits.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <dirent.h>
33 #include <strings.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <sys/mman.h>
38 #include <md5.h>
39 #include <pthread.h>
40
41 #include <cryptoutil.h>
42
43 #include <kmfapi.h>
44 #include <sys/crypto/elfsign.h>
45 #include <libelfsign.h>
46
47 #include <synch.h>
48
49 const char _PATH_ELFSIGN_CRYPTO_CERTS[] = CRYPTO_CERTS_DIR;
50 const char _PATH_ELFSIGN_ETC_CERTS[] = ETC_CERTS_DIR;
51
52 /*
53 * The CACERT and OBJCACERT are the Cryptographic Trust Anchors
54 * for the Solaris Cryptographic Framework.
55 *
56 * The SECACERT is the Signed Execution Trust Anchor that the
57 * Cryptographic Framework uses for FIPS-140 validation of non-crypto
58 * binaries
59 */
60 static const char _PATH_CRYPTO_CACERT[] = CRYPTO_CERTS_DIR "/CA";
61 static const char _PATH_CRYPTO_OBJCACERT[] = CRYPTO_CERTS_DIR "/SUNWObjectCA";
62 static const char _PATH_CRYPTO_SECACERT[] = ETC_CERTS_DIR "/SUNWSolarisCA";
63 static ELFCert_t CACERT = NULL;
64 static ELFCert_t OBJCACERT = NULL;
65 static ELFCert_t SECACERT = NULL;
66 static pthread_mutex_t ca_mutex = PTHREAD_MUTEX_INITIALIZER;
67
68 static void elfcertlib_freecert(ELFsign_t, ELFCert_t);
69 static ELFCert_t elfcertlib_allocatecert(void);
70
71 /*
72 * elfcertlib_verifycert - Verify the Cert with a Trust Anchor
73 *
74 * IN ess - elfsign context structure
75 * cert
76 * OUT NONE
77 * RETURN TRUE/FALSE
78 *
79 * We first setup the Trust Anchor (CA and SUNWObjectCA) certs
80 * if it hasn't been done already. We verify that the files on disk
81 * are those we expected.
82 *
83 * We then verify the given cert using the publickey of a TA.
84 * If the passed in cert is a TA or it has been verified already we
85 * short cut and return TRUE without futher validation.
86 */
87 /*ARGSUSED*/
88 boolean_t
elfcertlib_verifycert(ELFsign_t ess,ELFCert_t cert)89 elfcertlib_verifycert(ELFsign_t ess, ELFCert_t cert)
90 {
91 KMF_ATTRIBUTE attrlist[8];
92 int numattr;
93
94 KMF_RETURN rv;
95 if ((cert->c_verified == E_OK) || (cert->c_verified == E_IS_TA)) {
96 return (B_TRUE);
97 }
98
99 (void) pthread_mutex_lock(&ca_mutex);
100 if (CACERT == NULL) {
101 (void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_CACERT,
102 NULL, &CACERT, ES_GET);
103 }
104
105 if (OBJCACERT == NULL) {
106 (void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_OBJCACERT,
107 NULL, &OBJCACERT, ES_GET);
108 }
109
110 if (SECACERT == NULL) {
111 (void) elfcertlib_getcert(ess,
112 (char *)_PATH_CRYPTO_SECACERT, NULL, &SECACERT,
113 ES_GET_FIPS140);
114 }
115
116 (void) pthread_mutex_unlock(&ca_mutex);
117
118 if (CACERT != NULL) {
119 numattr = 0;
120 kmf_set_attr_at_index(attrlist, numattr++,
121 KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
122 sizeof (KMF_DATA));
123 kmf_set_attr_at_index(attrlist, numattr++,
124 KMF_SIGNER_CERT_DATA_ATTR, &CACERT->c_cert.certificate,
125 sizeof (KMF_DATA));
126
127 rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
128 if (rv == KMF_OK) {
129 if (ess->es_certCAcallback != NULL)
130 (ess->es_certvercallback)(ess->es_callbackctx,
131 cert, CACERT);
132 cert->c_verified = E_OK;
133 return (B_TRUE);
134 }
135 }
136
137 if (OBJCACERT != NULL) {
138 numattr = 0;
139 kmf_set_attr_at_index(attrlist, numattr++,
140 KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
141 sizeof (KMF_DATA));
142 kmf_set_attr_at_index(attrlist, numattr++,
143 KMF_SIGNER_CERT_DATA_ATTR, &OBJCACERT->c_cert.certificate,
144 sizeof (KMF_DATA));
145
146 rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
147 if (rv == KMF_OK) {
148 if (ess->es_certCAcallback != NULL)
149 (ess->es_certvercallback)(ess->es_callbackctx,
150 cert, OBJCACERT);
151 cert->c_verified = E_OK;
152 return (B_TRUE);
153 }
154 }
155
156 if (SECACERT != NULL) {
157 numattr = 0;
158 kmf_set_attr_at_index(attrlist, numattr++,
159 KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
160 sizeof (KMF_DATA));
161 kmf_set_attr_at_index(attrlist, numattr++,
162 KMF_SIGNER_CERT_DATA_ATTR, &SECACERT->c_cert.certificate,
163 sizeof (KMF_DATA));
164
165 rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
166 if (rv == KMF_OK) {
167 if (ess->es_certCAcallback != NULL)
168 (ess->es_certvercallback)(ess->es_callbackctx,
169 cert, SECACERT);
170 cert->c_verified = E_OK;
171 return (B_TRUE);
172 }
173 }
174
175 return (B_FALSE);
176 }
177
178 /*
179 * elfcertlib_getcert - Get the certificate for signer_DN
180 *
181 * IN ess - elfsign context structure
182 * cert_pathname - path to cert (May be NULL)
183 * signer_DN - The DN we are looking for (May be NULL)
184 * action - indicates crypto verification call
185 * OUT certp - allocated/loaded ELFCert_t
186 *
187 * If the cert_pathname is passed use it and don't search.
188 * Otherwise, go looking in certificate directories
189 */
190 boolean_t
elfcertlib_getcert(ELFsign_t ess,char * cert_pathname,char * signer_DN,ELFCert_t * certp,enum ES_ACTION action)191 elfcertlib_getcert(ELFsign_t ess, char *cert_pathname,
192 char *signer_DN, ELFCert_t *certp, enum ES_ACTION action)
193 {
194 KMF_RETURN rv;
195 ELFCert_t cert = NULL;
196 KMF_X509_DER_CERT certbuf[2];
197 uint32_t ncerts;
198 boolean_t ret = B_FALSE;
199 char *pathlist[3], **plp;
200
201 cryptodebug("elfcertlib_getcert: path=%s, DN=%s",
202 cert_pathname ? cert_pathname : "-none-",
203 signer_DN ? signer_DN : "-none-");
204 *certp = NULL;
205 if (cert_pathname == NULL && signer_DN == NULL) {
206 cryptodebug("elfcertlib_getcert: lack of specificity");
207 return (ret);
208 }
209
210 plp = pathlist;
211 if (cert_pathname != NULL) {
212 /* look in the specified object */
213 *plp++ = cert_pathname;
214 } else {
215 /* look in the certificate directories */
216 *plp++ = (char *)_PATH_ELFSIGN_CRYPTO_CERTS;
217 /*
218 * crypto verifications don't search beyond
219 * _PATH_ELFSIGN_CRYPTO_CERTS
220 */
221 if (action != ES_GET_CRYPTO)
222 *plp++ = (char *)_PATH_ELFSIGN_ETC_CERTS;
223 }
224 *plp = NULL;
225
226 if ((cert = elfcertlib_allocatecert()) == NULL) {
227 return (ret);
228 }
229
230 for (plp = pathlist; *plp; plp++) {
231 KMF_ATTRIBUTE attrlist[8];
232 KMF_KEYSTORE_TYPE kstype;
233 KMF_CERT_VALIDITY certvalidity;
234 int numattr;
235
236 kstype = KMF_KEYSTORE_OPENSSL;
237 certvalidity = KMF_ALL_CERTS;
238 ncerts = 2;
239
240 numattr = 0;
241 kmf_set_attr_at_index(attrlist, numattr++,
242 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
243 kmf_set_attr_at_index(attrlist, numattr++,
244 KMF_X509_DER_CERT_ATTR, certbuf,
245 sizeof (KMF_X509_DER_CERT));
246 kmf_set_attr_at_index(attrlist, numattr++,
247 KMF_COUNT_ATTR, &ncerts, sizeof (uint32_t));
248 if (signer_DN != NULL) {
249 kmf_set_attr_at_index(attrlist, numattr++,
250 KMF_SUBJECT_NAME_ATTR, signer_DN,
251 strlen(signer_DN));
252 }
253 kmf_set_attr_at_index(attrlist, numattr++,
254 KMF_CERT_VALIDITY_ATTR, &certvalidity,
255 sizeof (KMF_CERT_VALIDITY));
256 kmf_set_attr_at_index(attrlist, numattr++,
257 KMF_CERT_FILENAME_ATTR, *plp, strlen (*plp));
258
259 rv = kmf_find_cert(ess->es_kmfhandle, numattr, attrlist);
260
261 if (rv != KMF_OK)
262 continue;
263 /* found one */
264 cert->c_cert = certbuf[0];
265 if (ncerts > 1) {
266 /* release any extras */
267 kmf_free_kmf_cert(ess->es_kmfhandle, &certbuf[1]);
268 if (signer_DN == NULL) {
269 /* There can be only one */
270 cryptodebug("elfcertlib_getcert: "
271 "too many certificates found in %s",
272 cert_pathname);
273 goto cleanup;
274 }
275 }
276 /* cache subject and issuer */
277 rv = kmf_get_cert_subject_str(ess->es_kmfhandle,
278 &cert->c_cert.certificate, &cert->c_subject);
279 if (rv != KMF_OK)
280 goto cleanup;
281
282 rv = kmf_get_cert_issuer_str(ess->es_kmfhandle,
283 &cert->c_cert.certificate, &cert->c_issuer);
284 if (rv != KMF_OK)
285 goto cleanup;
286 break;
287 }
288 if (*plp == NULL) {
289 cryptodebug("elfcertlib_getcert: no certificate found");
290 goto cleanup;
291 }
292
293 cert->c_verified = E_UNCHECKED;
294
295 /*
296 * If the cert we are loading is the trust anchor (ie the CA) then
297 * we mark it as such in cert. This is so that we don't attempt
298 * to verify it later. The CA is always implicitly verified.
299 */
300 if (cert_pathname != NULL && (
301 strcmp(cert_pathname, _PATH_CRYPTO_CACERT) == 0 ||
302 strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0 ||
303 strcmp(cert_pathname, _PATH_CRYPTO_SECACERT) == 0)) {
304 if (ess->es_certCAcallback != NULL)
305 (ess->es_certCAcallback)(ess->es_callbackctx, cert,
306 cert_pathname);
307 cert->c_verified = E_IS_TA;
308 }
309
310 ret = B_TRUE;
311
312 cleanup:
313 if (ret) {
314 *certp = cert;
315 } else {
316 if (cert != NULL)
317 elfcertlib_freecert(ess, cert);
318 if (signer_DN != NULL)
319 cryptoerror(LOG_ERR, "unable to find a certificate "
320 "for DN: %s", signer_DN);
321 else
322 cryptoerror(LOG_ERR, "unable to load certificate "
323 "from %s", cert_pathname);
324 }
325 return (ret);
326 }
327
328 /*
329 * elfcertlib_loadprivatekey - Load the private key from path
330 *
331 * IN ess - elfsign context structure
332 * cert
333 * pathname
334 * OUT cert
335 * RETURNS TRUE/FALSE
336 */
337 boolean_t
elfcertlib_loadprivatekey(ELFsign_t ess,ELFCert_t cert,const char * pathname)338 elfcertlib_loadprivatekey(ELFsign_t ess, ELFCert_t cert, const char *pathname)
339 {
340 KMF_RETURN rv = KMF_OK;
341 KMF_KEY_HANDLE keybuf[2];
342 KMF_ATTRIBUTE attrlist[16];
343 uint32_t nkeys;
344 KMF_KEYSTORE_TYPE kstype;
345 KMF_KEY_ALG keytype;
346 KMF_KEY_CLASS keyclass;
347 KMF_ENCODE_FORMAT format;
348 int numattr;
349
350 kstype = KMF_KEYSTORE_OPENSSL;
351 nkeys = 2;
352 keytype = KMF_KEYALG_NONE;
353 keyclass = KMF_ASYM_PRI;
354 format = KMF_FORMAT_UNDEF;
355
356 numattr = 0;
357 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
358 &kstype, sizeof (kstype));
359 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
360 keybuf, sizeof (KMF_KEY_HANDLE));
361 kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR,
362 &nkeys, sizeof (uint32_t));
363 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR,
364 &keytype, sizeof (keytype));
365 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR,
366 &keyclass, sizeof (keyclass));
367 kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR,
368 &format, sizeof (format));
369 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_FILENAME_ATTR,
370 (char *)pathname, strlen(pathname));
371
372 rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist);
373 if (rv != KMF_OK)
374 return (B_FALSE);
375 if (nkeys != 1) {
376 /* lack of specificity */
377 cryptodebug("found %d keys at %s", nkeys, pathname);
378 return (B_FALSE);
379 }
380 cert->c_privatekey = keybuf[0];
381 cryptodebug("key %s loaded", pathname);
382 return (B_TRUE);
383 }
384
385 /*
386 * elfcertlib_loadtokenkey - Load the private key from token
387 *
388 * IN ess - elfsign context structure
389 * cert
390 * token_label
391 * pin
392 * OUT cert
393 * RETURNS TRUE/FALSE
394 */
395 boolean_t
elfcertlib_loadtokenkey(ELFsign_t ess,ELFCert_t cert,const char * token_label,const char * pin)396 elfcertlib_loadtokenkey(ELFsign_t ess, ELFCert_t cert,
397 const char *token_label, const char *pin)
398 {
399 KMF_RETURN rv;
400 char *idstr = NULL;
401 char *kmferr;
402 KMF_ATTRIBUTE attrlist[16];
403 uint32_t nkeys;
404 KMF_KEYSTORE_TYPE kstype;
405 KMF_KEY_ALG keytype;
406 KMF_KEY_CLASS keyclass;
407 KMF_ENCODE_FORMAT format;
408 KMF_CREDENTIAL pincred;
409 boolean_t tokenbool, privatebool;
410 int numattr;
411
412 /*
413 * We will search for the key based on the ID attribute
414 * which was added when the key was created. ID is
415 * a SHA-1 hash of the public modulus shared by the
416 * key and the certificate.
417 */
418 rv = kmf_get_cert_id_str(&cert->c_cert.certificate, &idstr);
419 if (rv != KMF_OK) {
420 (void) kmf_get_kmf_error_str(rv, &kmferr);
421 cryptodebug("Error getting ID from cert: %s\n",
422 (kmferr ? kmferr : "Unrecognized KMF error"));
423 free(kmferr);
424 return (B_FALSE);
425 }
426
427 kstype = KMF_KEYSTORE_PK11TOKEN;
428 nkeys = 1;
429 keytype = KMF_KEYALG_NONE;
430 keyclass = KMF_ASYM_PRI;
431 format = KMF_FORMAT_UNDEF;
432 pincred.cred = (char *)pin;
433 pincred.credlen = strlen(pin);
434 tokenbool = B_FALSE;
435 privatebool = B_TRUE;
436
437 numattr = 0;
438 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
439 &kstype, sizeof (kstype));
440 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
441 &cert->c_privatekey, sizeof (KMF_KEY_HANDLE));
442 kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR,
443 &nkeys, sizeof (uint32_t));
444 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR,
445 &keytype, sizeof (keytype));
446 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR,
447 &keyclass, sizeof (keyclass));
448 kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR,
449 &format, sizeof (format));
450 kmf_set_attr_at_index(attrlist, numattr++, KMF_IDSTR_ATTR,
451 idstr, strlen(idstr));
452 kmf_set_attr_at_index(attrlist, numattr++, KMF_CREDENTIAL_ATTR,
453 &pincred, sizeof (KMF_CREDENTIAL));
454 kmf_set_attr_at_index(attrlist, numattr++, KMF_TOKEN_BOOL_ATTR,
455 &tokenbool, sizeof (tokenbool));
456 kmf_set_attr_at_index(attrlist, numattr++, KMF_PRIVATE_BOOL_ATTR,
457 &privatebool, sizeof (privatebool));
458
459 rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist);
460 free(idstr);
461 if (rv != KMF_OK) {
462 (void) kmf_get_kmf_error_str(rv, &kmferr);
463 cryptodebug("Error finding private key: %s\n",
464 (kmferr ? kmferr : "Unrecognized KMF error"));
465 free(kmferr);
466 return (B_FALSE);
467 }
468 if (nkeys != 1) {
469 cryptodebug("Error finding private key: No key found\n");
470 return (B_FALSE);
471 }
472 cryptodebug("key found in %s", token_label);
473 cryptodebug("elfcertlib_loadprivatekey = 0x%.8X",
474 &cert->c_privatekey);
475
476 return (B_TRUE);
477 }
478
479 static const CK_BYTE MD5_DER_PREFIX[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
480 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
481
482 /*
483 * elfcertlib_sign - sign the given DATA using the privatekey in cert
484 *
485 * IN ess - elfsign context structure
486 * cert
487 * data
488 * data_len
489 * OUT sig - must be big enough to hold the signature of data
490 * Caller must allocate
491 * sig_len - actual length used; 0 on failure.
492 * RETURNS TRUE/FALSE
493 */
494 /*ARGSUSED*/
495 boolean_t
elfcertlib_sign(ELFsign_t ess,ELFCert_t cert,const uchar_t * data,size_t data_len,uchar_t * sig,size_t * sig_len)496 elfcertlib_sign(ELFsign_t ess, ELFCert_t cert,
497 const uchar_t *data, size_t data_len,
498 uchar_t *sig, size_t *sig_len)
499 {
500 KMF_RETURN ret;
501 KMF_DATA tobesigned;
502 KMF_DATA signature;
503 uchar_t der_data[sizeof (MD5_DER_PREFIX) + MD5_DIGEST_LENGTH];
504 KMF_ATTRIBUTE attrlist[8];
505 int numattr;
506
507 if (ess->es_version <= FILESIG_VERSION2) {
508 /* compatibility: take MD5 hash of SHA1 hash */
509 size_t derlen = MD5_DIGEST_LENGTH;
510 MD5_CTX ctx;
511
512 /*
513 * first: digest using software-based methods, don't
514 * rely on the token for hashing.
515 */
516 MD5Init(&ctx);
517 MD5Update(&ctx, data, data_len);
518 MD5Final(&der_data[sizeof (MD5_DER_PREFIX)], &ctx);
519
520 /*
521 * second: insert prefix
522 */
523 (void) memcpy(der_data, MD5_DER_PREFIX,
524 sizeof (MD5_DER_PREFIX));
525 /*
526 * prepare to sign the local buffer
527 */
528 tobesigned.Data = (uchar_t *)der_data;
529 tobesigned.Length = sizeof (MD5_DER_PREFIX) + derlen;
530 } else {
531 tobesigned.Data = (uchar_t *)data;
532 tobesigned.Length = data_len;
533 }
534
535 signature.Data = (uchar_t *)sig;
536 signature.Length = *sig_len;
537
538 numattr = 0;
539 kmf_set_attr_at_index(attrlist, numattr++,
540 KMF_KEYSTORE_TYPE_ATTR, &(cert->c_privatekey.kstype),
541 sizeof (KMF_KEYSTORE_TYPE));
542 kmf_set_attr_at_index(attrlist, numattr++,
543 KMF_KEY_HANDLE_ATTR, &cert->c_privatekey, sizeof (KMF_KEY_HANDLE));
544 kmf_set_attr_at_index(attrlist, numattr++,
545 KMF_OID_ATTR, (KMF_OID *)&KMFOID_RSA, sizeof (KMF_OID));
546 kmf_set_attr_at_index(attrlist, numattr++,
547 KMF_DATA_ATTR, &tobesigned, sizeof (KMF_DATA));
548 kmf_set_attr_at_index(attrlist, numattr++,
549 KMF_OUT_DATA_ATTR, &signature, sizeof (KMF_DATA));
550
551 ret = kmf_sign_data(ess->es_kmfhandle, numattr, attrlist);
552
553 if (ret != KMF_OK) {
554 char *kmferr;
555
556 (void) kmf_get_kmf_error_str(ret, &kmferr);
557 cryptodebug("Error signing data: %s\n",
558 (kmferr ? kmferr : "Unrecognized KMF error"));
559 free(kmferr);
560 *sig_len = 0;
561 return (B_FALSE);
562 }
563 *sig_len = signature.Length;
564 return (B_TRUE);
565 }
566
567 /*
568 * elfcertlib_verifysig - verify the given DATA using the public key in cert
569 *
570 * IN ess - elfsign context structure
571 * cert
572 * signature
573 * sig_len
574 * data
575 * data_len
576 * OUT N/A
577 * RETURNS TRUE/FALSE
578 */
579 boolean_t
elfcertlib_verifysig(ELFsign_t ess,ELFCert_t cert,const uchar_t * signature,size_t sig_len,const uchar_t * data,size_t data_len)580 elfcertlib_verifysig(ELFsign_t ess, ELFCert_t cert,
581 const uchar_t *signature, size_t sig_len,
582 const uchar_t *data, size_t data_len)
583 {
584 KMF_RETURN rv;
585 KMF_DATA indata;
586 KMF_DATA insig;
587 KMF_ALGORITHM_INDEX algid;
588 KMF_ATTRIBUTE attrlist[8];
589 KMF_KEYSTORE_TYPE kstype;
590 int numattr;
591
592 indata.Data = (uchar_t *)data;
593 indata.Length = data_len;
594 insig.Data = (uchar_t *)signature;
595 insig.Length = sig_len;
596
597 if (ess->es_version <= FILESIG_VERSION2)
598 algid = KMF_ALGID_MD5WithRSA;
599 else
600 algid = KMF_ALGID_RSA;
601
602 /*
603 * We tell KMF to use the PKCS11 verification APIs
604 * here to prevent the use of OpenSSL and to keep
605 * all validation within the FIPS-140 boundary for
606 * the Cryptographic Framework.
607 */
608 kstype = KMF_KEYSTORE_PK11TOKEN;
609
610 numattr = 0;
611 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
612 &kstype, sizeof (kstype));
613 kmf_set_attr_at_index(attrlist, numattr++, KMF_DATA_ATTR,
614 &indata, sizeof (KMF_DATA));
615 kmf_set_attr_at_index(attrlist, numattr++, KMF_IN_SIGN_ATTR,
616 &insig, sizeof (KMF_DATA));
617 kmf_set_attr_at_index(attrlist, numattr++, KMF_SIGNER_CERT_DATA_ATTR,
618 (KMF_DATA *)(&cert->c_cert.certificate), sizeof (KMF_DATA));
619 kmf_set_attr_at_index(attrlist, numattr++, KMF_ALGORITHM_INDEX_ATTR,
620 &algid, sizeof (algid));
621
622 rv = kmf_verify_data(ess->es_kmfhandle, numattr, attrlist);
623
624 return ((rv == KMF_OK));
625 }
626
627 /*
628 * elfcertlib_getdn
629 *
630 * IN cert
631 * OUT NONE
632 * RETURN dn or NULL
633 */
634 char *
elfcertlib_getdn(ELFCert_t cert)635 elfcertlib_getdn(ELFCert_t cert)
636 {
637 cryptodebug("elfcertlib_getdn");
638
639 return (cert->c_subject);
640 }
641
642 /*
643 * elfcertlib_getissuer
644 *
645 * IN cert
646 * OUT NONE
647 * RETURN dn or NULL
648 */
649 char *
elfcertlib_getissuer(ELFCert_t cert)650 elfcertlib_getissuer(ELFCert_t cert)
651 {
652 cryptodebug("elfcertlib_issuer");
653
654 return (cert->c_issuer);
655 }
656
657 boolean_t
elfcertlib_init(ELFsign_t ess)658 elfcertlib_init(ELFsign_t ess)
659 {
660 boolean_t rc = B_TRUE;
661 KMF_RETURN rv;
662 if (ess->es_kmfhandle == NULL) {
663 rv = kmf_initialize(&ess->es_kmfhandle, NULL, NULL);
664 if (rv != KMF_OK) {
665 cryptoerror(LOG_ERR,
666 "unable to initialize KMF library");
667 rc = B_FALSE;
668 }
669 }
670 return (rc);
671 }
672
673 void
elfcertlib_fini(ELFsign_t ess)674 elfcertlib_fini(ELFsign_t ess)
675 {
676 (void) kmf_finalize(ess->es_kmfhandle);
677 }
678
679 /*
680 * set the token device
681 */
682 boolean_t
elfcertlib_settoken(ELFsign_t ess,char * token)683 elfcertlib_settoken(ELFsign_t ess, char *token)
684 {
685 boolean_t rc = B_TRUE;
686 KMF_RETURN rv;
687 KMF_ATTRIBUTE attrlist[8];
688 KMF_KEYSTORE_TYPE kstype;
689 boolean_t readonly;
690 int numattr;
691
692 kstype = KMF_KEYSTORE_PK11TOKEN;
693 readonly = B_TRUE;
694
695 numattr = 0;
696 kmf_set_attr_at_index(attrlist, numattr++,
697 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
698 kmf_set_attr_at_index(attrlist, numattr++,
699 KMF_TOKEN_LABEL_ATTR, token, strlen(token));
700 kmf_set_attr_at_index(attrlist, numattr++,
701 KMF_READONLY_ATTR, &readonly, sizeof (readonly));
702
703 rv = kmf_configure_keystore(ess->es_kmfhandle, numattr, attrlist);
704 if (rv != KMF_OK) {
705 cryptoerror(LOG_ERR, "unable to select token\n");
706 rc = B_FALSE;
707 }
708
709 return (rc);
710 }
711
712 /*
713 * set the certificate CA identification callback
714 */
715 void
elfcertlib_setcertCAcallback(ELFsign_t ess,void (* cb)(void *,ELFCert_t,char *))716 elfcertlib_setcertCAcallback(ELFsign_t ess,
717 void (*cb)(void *, ELFCert_t, char *))
718 {
719 ess->es_certCAcallback = cb;
720 }
721
722 /*
723 * set the certificate verification callback
724 */
725 void
elfcertlib_setcertvercallback(ELFsign_t ess,void (* cb)(void *,ELFCert_t,ELFCert_t))726 elfcertlib_setcertvercallback(ELFsign_t ess,
727 void (*cb)(void *, ELFCert_t, ELFCert_t))
728 {
729 ess->es_certvercallback = cb;
730 }
731
732
733 /*
734 * elfcertlib_releasecert - release a cert
735 *
736 * IN cert
737 * OUT cert
738 * RETURN N/A
739 *
740 */
741 void
elfcertlib_releasecert(ELFsign_t ess,ELFCert_t cert)742 elfcertlib_releasecert(ELFsign_t ess, ELFCert_t cert)
743 {
744 elfcertlib_freecert(ess, cert);
745 }
746
747 /*
748 * elfcertlib_allocatecert - create a new ELFCert_t
749 *
750 * IN N/A
751 * OUT N/A
752 * RETURN ELFCert_t, NULL on failure.
753 */
754 static ELFCert_t
elfcertlib_allocatecert(void)755 elfcertlib_allocatecert(void)
756 {
757 ELFCert_t cert = NULL;
758
759 cert = malloc(sizeof (struct ELFCert_s));
760 if (cert == NULL) {
761 cryptoerror(LOG_ERR,
762 "elfcertlib_allocatecert: malloc failed %s",
763 strerror(errno));
764 return (NULL);
765 }
766 (void) memset(cert, 0, sizeof (struct ELFCert_s));
767 cert->c_verified = E_UNCHECKED;
768 cert->c_subject = NULL;
769 cert->c_issuer = NULL;
770 return (cert);
771 }
772
773 /*
774 * elfcertlib_freecert - freeup the memory of a cert
775 *
776 * IN cert
777 * OUT cert
778 * RETURN N/A
779 *
780 */
781 static void
elfcertlib_freecert(ELFsign_t ess,ELFCert_t cert)782 elfcertlib_freecert(ELFsign_t ess, ELFCert_t cert)
783 {
784 if (cert == NULL)
785 return;
786
787 free(cert->c_subject);
788 free(cert->c_issuer);
789
790 kmf_free_kmf_cert(ess->es_kmfhandle, &cert->c_cert);
791 kmf_free_kmf_key(ess->es_kmfhandle, &cert->c_privatekey);
792
793 free(cert);
794 }
795