2 * ====================================================================
3 * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
17 * 3. All advertising materials mentioning features or use of this
18 * software must display the following acknowledgment:
19 * "This product includes software developed by the OpenSSL Project
20 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 * endorse or promote products derived from this software without
24 * prior written permission. For written permission, please contact
25 * licensing@OpenSSL.org.
27 * 5. Products derived from this software may not be called "OpenSSL"
28 * nor may "OpenSSL" appear in their names without prior written
29 * permission of the OpenSSL Project.
31 * 6. Redistributions of any form whatsoever must retain the following
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 * OF THE POSSIBILITY OF SUCH DAMAGE.
48 * ====================================================================
50 * This product includes cryptographic software written by Eric Young
51 * (eay@cryptsoft.com). This product includes software written by Tim
52 * Hudson (tjh@cryptsoft.com).
57 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
58 * Use is subject to license terms.
62 * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
65 #pragma ident "%Z%%M% %I% %E% SMI"
71 #include <openssl/crypto.h>
72 #include <openssl/err.h>
73 #include <openssl/x509.h>
74 #include <openssl/ssl.h>
76 #include <openssl/pkcs12.h>
82 * sunw_cryto_init() does crypto-specific initialization.
91 sunw_crypto_init(void)
93 OpenSSL_add_all_algorithms();
94 SSL_load_error_strings();
95 ERR_load_SUNW_strings();
96 (void) SSL_library_init();
100 * sunw_split_certs() - Given a list of certs and a list of private keys,
101 * moves certs which match one of the keys to a different stack.
104 * allkeys - Points to a stack of private keys to search.
105 * allcerts - Points to a stack of certs to be searched.
106 * keycerts - Points to address of a stack of certs with matching private
107 * keys. They are moved from 'allcerts'. This may not be NULL
108 * when called. If *keycerts is NULL upon entry, a new stack will
109 * be allocated. Otherwise, it must be a valid STACK_OF(509).
110 * nocerts - Points to address of a stack for keys which have no matching
111 * certs. Keys are moved from 'allkeys' here when they have no
112 * matching certs. If this is NULL, matchless keys will be
115 * Notes: If an error occurs while moving certs, the cert being move may be
116 * lost. 'keycerts' may only contain part of the matching certs. The number
117 * of certs successfully moved can be found by checking sk_X509_num(keycerts).
119 * If there is a key which does not have a matching cert, it is moved to
122 * If all certs are removed from 'certs' and/or 'pkeys', it will be the
123 * caller's responsibility to free the empty stacks.
126 * < 0 - An error returned. Call ERR_get_error() to get errors information.
127 * Where possible, memory has been freed.
128 * >= 0 - The number of certs moved from 'cert' to 'pkcerts'.
131 sunw_split_certs(STACK_OF(EVP_PKEY
) *allkeys
, STACK_OF(X509
) *allcerts
,
132 STACK_OF(X509
) **keycerts
, STACK_OF(EVP_PKEY
) **nocerts
)
134 STACK_OF(X509
) *matching
;
135 STACK_OF(EVP_PKEY
) *nomatch
;
149 if ((matching
= sk_X509_new_null()) == NULL
) {
150 SUNWerr(SUNW_F_SPLIT_CERTS
, SUNW_R_MEMORY_FAILURE
);
153 *keycerts
= matching
;
156 while (k
< sk_EVP_PKEY_num(allkeys
)) {
158 tmpkey
= sk_EVP_PKEY_value(allkeys
, k
);
160 for (i
= 0; i
< sk_X509_num(allcerts
); i
++) {
161 tmpcert
= sk_X509_value(allcerts
, i
);
162 res
= X509_check_private_key(tmpcert
, tmpkey
);
166 tmpcert
= sk_X509_delete(allcerts
, i
);
167 if (sk_X509_push(matching
, tmpcert
) == 0) {
169 SUNWerr(SUNW_F_SPLIT_CERTS
,
170 SUNW_R_MEMORY_FAILURE
);
178 * Found a match - keep the key & check out the next
184 * No cert matching this key. Move the key if
185 * possible or discard it. Don't increment the
188 if (nocerts
== NULL
) {
189 tmpkey
= sk_EVP_PKEY_delete(allkeys
, k
);
190 sunw_evp_pkey_free(tmpkey
);
192 if (*nocerts
== NULL
) {
193 nomatch
= sk_EVP_PKEY_new_null();
194 if (nomatch
== NULL
) {
195 SUNWerr(SUNW_F_SPLIT_CERTS
,
196 SUNW_R_MEMORY_FAILURE
);
201 tmpkey
= sk_EVP_PKEY_delete(allkeys
, k
);
202 if (sk_EVP_PKEY_push(nomatch
, tmpkey
) == 0) {
203 sunw_evp_pkey_free(tmpkey
);
204 SUNWerr(SUNW_F_SPLIT_CERTS
,
205 SUNW_R_MEMORY_FAILURE
);
216 * sunw_evp_pkey_free() Given an EVP_PKEY structure, free any attributes
217 * that are attached. Then free the EVP_PKEY itself.
219 * This is a replacement for EVP_PKEY_free() for the sunw stuff.
220 * It should be used in places where EVP_PKEY_free would be used,
221 * including calls to sk_EVP_PKEY_pop_free().
224 * pkey - Entry which potentially has attributes to be freed.
230 sunw_evp_pkey_free(EVP_PKEY
*pkey
)
233 if (pkey
->attributes
!= NULL
) {
234 sk_X509_ATTRIBUTE_pop_free(pkey
->attributes
,
235 X509_ATTRIBUTE_free
);
236 pkey
->attributes
= NULL
;
243 * sunw_set_localkeyid() sets the localkeyid in a cert, a private key or
244 * both. Any existing localkeyid will be discarded.
247 * keyid_str- A byte string with the localkeyid to set
248 * keyid_len- Length of the keyid byte string.
249 * pkey - Points to a private key to set the keyidstr in.
250 * cert - Points to a cert to set the keyidstr in.
252 * Note that setting a keyid into a cert which will not be written out as
253 * a PKCS12 cert is pointless since it will be lost.
257 * < 0 - An error occurred. It was probably an error in allocating
258 * memory. The error will be set in the error stack. Call
259 * ERR_get_error() to get specific information.
262 sunw_set_localkeyid(const char *keyid_str
, int keyid_len
, EVP_PKEY
*pkey
,
265 X509_ATTRIBUTE
*attr
= NULL
;
266 ASN1_STRING
*str
= NULL
;
267 ASN1_TYPE
*keyid
= NULL
;
272 if (X509_keyid_set1(cert
, (uchar_t
*)keyid_str
, keyid_len
)
274 SUNWerr(SUNW_F_SET_LOCALKEYID
, SUNW_R_SET_LKID_ERR
);
279 str
= (ASN1_STRING
*)M_ASN1_OCTET_STRING_new();
281 M_ASN1_OCTET_STRING_set(str
, keyid_str
, keyid_len
) == 0 ||
282 (keyid
= ASN1_TYPE_new()) == NULL
) {
283 SUNWerr(SUNW_F_SET_LOCALKEYID
, SUNW_R_MEMORY_FAILURE
);
287 ASN1_TYPE_set(keyid
, V_ASN1_OCTET_STRING
, str
);
290 attr
= type2attrib(keyid
, NID_localKeyID
);
293 * Error already on stack
299 if (pkey
->attributes
== NULL
) {
300 pkey
->attributes
= sk_X509_ATTRIBUTE_new_null();
301 if (pkey
->attributes
== NULL
) {
302 SUNWerr(SUNW_F_SET_LOCALKEYID
,
303 SUNW_R_MEMORY_FAILURE
);
307 i
= find_attr_by_nid(pkey
->attributes
, NID_localKeyID
);
309 sk_X509_ATTRIBUTE_delete(pkey
->attributes
, i
);
311 if (sk_X509_ATTRIBUTE_push(pkey
->attributes
, attr
) == 0) {
312 SUNWerr(SUNW_F_SET_LOCALKEYID
, SUNW_R_MEMORY_FAILURE
);
321 ASN1_STRING_free(str
);
323 ASN1_TYPE_free(keyid
);
325 X509_ATTRIBUTE_free(attr
);
331 * sunw_get_pkey_localkeyid() gets the localkeyid from a private key. It can
332 * optionally remove the value found.
335 * dowhat - What to do with the attributes (remove them or copy them).
336 * pkey - Points to a private key to set the keyidstr in.
337 * keyid_str- Points to a location which will receive the pointer to
338 * a byte string containing the binary localkeyid. Note that
339 * this is a copy, and the caller must free it.
340 * keyid_len- Length of keyid_str.
343 * >= 0 - The number of characters in the keyid returned.
344 * < 0 - An error occurred. It was probably an error in allocating
345 * memory. The error will be set in the error stack. Call
346 * ERR_get_error() to get specific information.
349 sunw_get_pkey_localkeyid(getdo_actions_t dowhat
, EVP_PKEY
*pkey
,
350 char **keyid_str
, int *keyid_len
)
352 X509_ATTRIBUTE
*attr
= NULL
;
353 ASN1_OCTET_STRING
*str
= NULL
;
354 ASN1_TYPE
*ty
= NULL
;
358 if (keyid_str
!= NULL
)
360 if (keyid_len
!= NULL
)
363 if (pkey
== NULL
|| pkey
->attributes
== NULL
) {
367 if ((i
= find_attr_by_nid(pkey
->attributes
, NID_localKeyID
)) < 0) {
370 attr
= sk_X509_ATTRIBUTE_value(pkey
->attributes
, i
);
372 if ((ty
= attrib2type(attr
)) == NULL
||
373 ty
->type
!= V_ASN1_OCTET_STRING
) {
377 if (dowhat
== GETDO_DEL
) {
378 attr
= sk_X509_ATTRIBUTE_delete(pkey
->attributes
, i
);
380 X509_ATTRIBUTE_free(attr
);
384 str
= ty
->value
.octet_string
;
386 if ((*keyid_str
= malloc(len
)) == NULL
) {
387 SUNWerr(SUNW_F_GET_LOCALKEYID
, SUNW_R_MEMORY_FAILURE
);
391 (void) memcpy(*keyid_str
, str
->data
, len
);
398 * sunw_get_pkey_fname() gets the friendlyName from a private key. It can
399 * optionally remove the value found.
402 * dowhat - What to do with the attributes (remove them or copy them).
403 * pkey - Points to a private key to get the frientlyname from
404 * fname - Points to a location which will receive the pointer to a
405 * byte string with the ASCII friendlyname
408 * >= 0 - The number of characters in the frienlyname returned.
409 * < 0 - An error occurred. It was probably an error in allocating
410 * memory. The error will be set in the error stack. Call
411 * ERR_get_error() to get specific information.
414 sunw_get_pkey_fname(getdo_actions_t dowhat
, EVP_PKEY
*pkey
, char **fname
)
416 X509_ATTRIBUTE
*attr
= NULL
;
417 ASN1_BMPSTRING
*str
= NULL
;
418 ASN1_TYPE
*ty
= NULL
;
425 if (pkey
== NULL
|| pkey
->attributes
== NULL
) {
429 if ((i
= find_attr_by_nid(pkey
->attributes
, NID_friendlyName
)) < 0) {
432 attr
= sk_X509_ATTRIBUTE_value(pkey
->attributes
, i
);
434 if ((ty
= attrib2type(attr
)) == NULL
||
435 ty
->type
!= V_ASN1_BMPSTRING
) {
439 if (dowhat
== GETDO_DEL
) {
440 attr
= sk_X509_ATTRIBUTE_delete(pkey
->attributes
, i
);
442 X509_ATTRIBUTE_free(attr
);
446 str
= ty
->value
.bmpstring
;
447 #if OPENSSL_VERSION_NUMBER < 0x10000000L
448 *fname
= uni2asc(str
->data
, str
->length
);
450 *fname
= OPENSSL_uni2asc(str
->data
, str
->length
);
452 if (*fname
== NULL
) {
453 SUNWerr(SUNW_F_GET_PKEY_FNAME
, SUNW_R_MEMORY_FAILURE
);
457 len
= strlen(*fname
);
463 * sunw_find_localkeyid() searches stacks of certs and private keys,
464 * and returns the first matching cert/private key found.
466 * Look for a keyid in a stack of certs. if 'certs' is NULL and 'pkeys' is
467 * not NULL, search the list of private keys. Move the matching cert to
468 * 'matching_cert' and its matching private key to 'matching_pkey'. If no
469 * cert or keys match, no match occurred.
472 * keyid_str- A byte string with the localkeyid to match
473 * keyid_len- Length of the keyid byte string.
474 * pkeys - Points to a stack of private keys which match the certs.
475 * This may be NULL, in which case no keys are returned.
476 * certs - Points to a stack of certs to search. If NULL, search the
477 * stack of keys instead.
479 * - Pointer to receive address of first matching pkey found.
480 * 'matching_pkey' must not be NULL; '*matching_pkey' will be
483 * - Pointer to receive address of first matching cert found.
484 * 'matching_cert' must not be NULL; '*matching_cert' will be
488 * < 0 - An error returned. Call ERR_get_error() to get errors information.
489 * Where possible, memory has been freed.
490 * >= 0 - Objects were found and returned. Which objects are indicated by
491 * which bits are set (FOUND_PKEY and/or FOUND_CERT).
494 sunw_find_localkeyid(char *keyid_str
, int len
, STACK_OF(EVP_PKEY
) *pkeys
,
495 STACK_OF(X509
) *certs
, EVP_PKEY
**matching_pkey
, X509
**matching_cert
)
497 ASN1_STRING
*cmpstr
= NULL
;
498 EVP_PKEY
*tmp_pkey
= NULL
;
499 X509
*tmp_cert
= NULL
;
502 /* If NULL arguments, this is an error */
503 if (keyid_str
== NULL
||
504 (pkeys
== NULL
|| certs
== NULL
) ||
505 (pkeys
!= NULL
&& matching_pkey
== NULL
) ||
506 (certs
!= NULL
&& matching_cert
== NULL
)) {
507 SUNWerr(SUNW_F_FIND_LOCALKEYID
, SUNW_R_INVALID_ARG
);
511 if (matching_pkey
!= NULL
)
512 *matching_pkey
= NULL
;
513 if (matching_cert
!= NULL
)
514 *matching_cert
= NULL
;
516 cmpstr
= (ASN1_STRING
*)M_ASN1_OCTET_STRING_new();
517 if (cmpstr
== NULL
||
518 M_ASN1_OCTET_STRING_set(cmpstr
, keyid_str
, len
) == 0) {
519 SUNWerr(SUNW_F_FIND_LOCALKEYID
, SUNW_R_MEMORY_FAILURE
);
523 retval
= find_attr(NID_localKeyID
, cmpstr
, pkeys
, &tmp_pkey
, certs
,
526 ASN1_STRING_free(cmpstr
);
530 if (matching_pkey
!= NULL
)
531 *matching_pkey
= tmp_pkey
;
532 if (matching_cert
!= NULL
)
533 *matching_cert
= tmp_cert
;
539 * sunw_find_fname() searches stacks of certs and private keys for one with
540 * a matching friendlyname and returns the first matching cert/private
543 * Look for a friendlyname in a stack of certs. if 'certs' is NULL and 'pkeys'
544 * is not NULL, search the list of private keys. Move the matching cert to
545 * 'matching_cert' and its matching private key to 'matching_pkey'. If no
546 * cert or keys match, no match occurred.
549 * fname - Friendlyname to find (NULL-terminated ASCII string).
550 * pkeys - Points to a stack of private keys which match the certs.
551 * This may be NULL, in which case no keys are returned.
552 * certs - Points to a stack of certs to search. If NULL, search the
553 * stack of keys instead.
555 * - Pointer to receive address of first matching pkey found.
557 * - Pointer to receive address of first matching cert found.
560 * < 0 - An error returned. Call ERR_get_error() to get errors information.
561 * Where possible, memory has been freed.
562 * >= 0 - Objects were found and returned. Which objects are indicated by
563 * which bits are set (FOUND_PKEY and/or FOUND_CERT).
566 sunw_find_fname(char *fname
, STACK_OF(EVP_PKEY
) *pkeys
, STACK_OF(X509
) *certs
,
567 EVP_PKEY
**matching_pkey
, X509
** matching_cert
)
569 ASN1_STRING
*cmpstr
= NULL
;
570 EVP_PKEY
*tmp_pkey
= NULL
;
571 X509
*tmp_cert
= NULL
;
574 /* If NULL arguments, this is an error */
576 (pkeys
== NULL
|| certs
== NULL
) ||
577 (pkeys
!= NULL
&& matching_pkey
== NULL
) ||
578 (certs
!= NULL
&& matching_cert
== NULL
)) {
579 SUNWerr(SUNW_F_FIND_FNAME
, SUNW_R_INVALID_ARG
);
583 if (matching_pkey
!= NULL
)
584 *matching_pkey
= NULL
;
585 if (matching_cert
!= NULL
)
586 *matching_cert
= NULL
;
588 cmpstr
= (ASN1_STRING
*)asc2bmpstring(fname
, strlen(fname
));
589 if (cmpstr
== NULL
) {
591 * Error already on stack
596 retval
= find_attr(NID_friendlyName
, cmpstr
, pkeys
, &tmp_pkey
, certs
,
599 ASN1_STRING_free(cmpstr
);
603 if (matching_pkey
!= NULL
)
604 *matching_pkey
= tmp_pkey
;
605 if (matching_cert
!= NULL
)
606 *matching_cert
= tmp_cert
;
612 * sunw_print_times() formats and prints cert times to the given file.
614 * The label is printed on one line. One or both dates are printed on
615 * the following line or two, each with it's own indented label in the
619 * 'not before' date: whatever
620 * 'not after' date: whatever
623 * fp - file pointer for file to write to.
624 * dowhat - what field(s) to print.
625 * label - Label to use. If NULL, no line will be printed.
626 * cert - Points to a client or CA certs to check
629 * < 0 - An error occured.
630 * >= 0 - Number of lines written.
633 sunw_print_times(FILE *fp
, prnt_actions_t dowhat
, char *label
, X509
*cert
)
638 (void) fprintf(fp
, "%s\n", label
);
642 if (dowhat
== PRNT_NOT_BEFORE
|| dowhat
== PRNT_BOTH
) {
643 (void) fprintf(fp
, "'not before' date: ");
644 (void) print_time(fp
, X509_get_notBefore(cert
));
645 (void) fprintf(fp
, "\n");
649 if (dowhat
== PRNT_NOT_AFTER
|| dowhat
== PRNT_BOTH
) {
650 (void) fprintf(fp
, "'not after' date: ");
651 (void) print_time(fp
, X509_get_notAfter(cert
));
652 (void) fprintf(fp
, "\n");
659 * sunw_check_keys() compares the public key in the certificate and a
660 * private key to ensure that they match.
663 * cert - Points to a certificate.
664 * pkey - Points to a private key.
667 * == 0 - These do not match.
668 * != 0 - The cert's public key and the private key match.
671 sunw_check_keys(X509
*cert
, EVP_PKEY
*pkey
)
675 if (pkey
!= NULL
&& cert
!= NULL
)
676 retval
= X509_check_private_key(cert
, pkey
);
682 * sunw_issuer_attrs - Given a cert, return the issuer-specific attributes
683 * as one ASCII string.
686 * cert - Cert to process
687 * buf - If non-NULL, buffer to receive string. If NULL, one will
688 * be allocated and its value will be returned to the caller.
689 * len - If 'buff' is non-null, the buffer's length.
691 * This returns an ASCII string with all issuer-related attributes in one
692 * string separated by '/' characters. Each attribute begins with its name
693 * and an equal sign. Two attributes (ATTR1 and Attr2) would have the
696 * ATTR1=attr_value/ATTR2=attr2_value
699 * != NULL - Pointer to the ASCII string containing the issuer-related
700 * attributes. If the 'buf' argument was NULL, this is a
701 * dynamically-allocated buffer and the caller will have the
702 * responsibility for freeing it.
703 * NULL - Memory needed to be allocated but could not be. Errors
704 * are set on the error stack.
707 sunw_issuer_attrs(X509
*cert
, char *buf
, int len
)
709 return (X509_NAME_oneline(X509_get_issuer_name(cert
), buf
, len
));
713 * sunw_subject_attrs - Given a cert, return the subject-specific attributes
714 * as one ASCII string.
717 * cert - Cert to process
718 * buf - If non-NULL, buffer to receive string. If NULL, one will
719 * be allocated and its value will be returned to the caller.
720 * len - If 'buff' is non-null, the buffer's length.
722 * This returns an ASCII string with all subject-related attributes in one
723 * string separated by '/' characters. Each attribute begins with its name
724 * and an equal sign. Two attributes (ATTR1 and Attr2) would have the
727 * ATTR1=attr_value/ATTR2=attr2_value
730 * != NULL - Pointer to the ASCII string containing the subject-related
731 * attributes. If the 'buf' argument was NULL, this is a
732 * dynamically-allocated buffer and the caller will have the
733 * responsibility for freeing it.
734 * NULL - Memory needed to be allocated but could not be. Errors
735 * are set on the error stack.
738 sunw_subject_attrs(X509
*cert
, char *buf
, int len
)
740 return (X509_NAME_oneline(X509_get_subject_name(cert
), buf
, len
));
744 * sunw_append_keys - Given two stacks of private keys, remove the keys from
745 * the second stack and append them to the first. Both stacks must exist
749 * dst - the stack to receive the keys from 'src'
750 * src - the stack whose keys are to be moved.
753 * -1 - An error occurred. The error status is set.
754 * >= 0 - The number of keys that were copied.
757 sunw_append_keys(STACK_OF(EVP_PKEY
) *dst
, STACK_OF(EVP_PKEY
) *src
)
762 while (sk_EVP_PKEY_num(src
) > 0) {
763 tmpk
= sk_EVP_PKEY_delete(src
, 0);
764 if (sk_EVP_PKEY_push(dst
, tmpk
) == 0) {
765 sunw_evp_pkey_free(tmpk
);
766 SUNWerr(SUNW_F_APPEND_KEYS
, SUNW_R_MEMORY_FAILURE
);