14 * portion of this software, then the disclaimer below must
15 * also be included.
16 *
17 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGES.
29 */
30
31 /*
32 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
33 * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
34 */
35
36 #include <errno.h>
37 #include <string.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <dlfcn.h>
41 #include <unistd.h>
42 #include <dirent.h>
43
44
45 /* Solaris Kerberos */
46 #include <libintl.h>
47 #include <assert.h>
48 #include <security/pam_appl.h>
49 #include <ctype.h>
50 #include "k5-int.h"
51 #include <ctype.h>
52
53 /*
352 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
353 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
354 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
355 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
356 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
357 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
358 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
359 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
360 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
361 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
362 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
363 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
364 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
365 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
366 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
367 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
368 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
369 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
370 };
371
372 /* Solaris Kerberos */
373 static k5_mutex_t oids_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
374 static int pkinit_oids_refs = 0;
375
376 krb5_error_code
377 pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx) {
378
379 krb5_error_code retval = ENOMEM;
380 pkinit_plg_crypto_context ctx = NULL;
381
382 /* initialize openssl routines */
383 /* Solaris Kerberos */
384 retval = openssl_init();
385 if (retval != 0)
386 goto out;
387
388 ctx = (pkinit_plg_crypto_context)malloc(sizeof(*ctx));
389 if (ctx == NULL)
390 goto out;
391 (void) memset(ctx, 0, sizeof(*ctx));
392
393 pkiDebug("%s: initializing openssl crypto context at %p\n",
394 __FUNCTION__, ctx);
395 retval = pkinit_init_pkinit_oids(ctx);
490 }
491
492 void
493 pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)
494 {
495 if (req_cryptoctx == NULL)
496 return;
497
498 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, req_cryptoctx);
499 if (req_cryptoctx->dh != NULL)
500 DH_free(req_cryptoctx->dh);
501 if (req_cryptoctx->received_cert != NULL)
502 X509_free(req_cryptoctx->received_cert);
503
504 free(req_cryptoctx);
505 }
506
507 static krb5_error_code
508 pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)
509 {
510 krb5_error_code retval = ENOMEM;
511 int nid = 0;
512
513 /*
514 * If OpenSSL already knows about the OID, use the
515 * existing definition. Otherwise, create an OID object.
516 */
517 #define CREATE_OBJ_IF_NEEDED(oid, vn, sn, ln) \
518 nid = OBJ_txt2nid(oid); \
519 if (nid == NID_undef) { \
520 nid = OBJ_create(oid, sn, ln); \
521 if (nid == NID_undef) { \
522 pkiDebug("Error creating oid object for '%s'\n", oid); \
523 goto out; \
524 } \
525 } \
526 ctx->vn = OBJ_nid2obj(nid);
527
528 /* Solaris Kerberos */
529 retval = k5_mutex_lock(&oids_mutex);
530 if (retval != 0)
531 goto out;
532
533 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.2", id_pkinit_san,
534 "id-pkinit-san", "KRB5PrincipalName");
535
536 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.1", id_pkinit_authData,
537 "id-pkinit-authdata", "PKINIT signedAuthPack");
538
539 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.2", id_pkinit_DHKeyData,
540 "id-pkinit-DHKeyData", "PKINIT dhSignedData");
541
542 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.3", id_pkinit_rkeyData,
543 "id-pkinit-rkeyData", "PKINIT encKeyPack");
544
545 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.4", id_pkinit_KPClientAuth,
546 "id-pkinit-KPClientAuth", "PKINIT Client EKU");
547
548 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.5", id_pkinit_KPKdc,
549 "id-pkinit-KPKdc", "KDC EKU");
550
551 #if 0
552 CREATE_OBJ_IF_NEEDED("1.2.840.113549.1.7.1", id_pkinit_authData9,
553 "id-pkcs7-data", "PKCS7 data");
554 #else
555 /* See note in pkinit_pkcs7type2oid() */
556 ctx->id_pkinit_authData9 = NULL;
557 #endif
558
559 CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.2", id_ms_kp_sc_logon,
560 "id-ms-kp-sc-logon EKU", "Microsoft SmartCard Login EKU");
561
562 CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.3", id_ms_san_upn,
563 "id-ms-san-upn", "Microsoft Universal Principal Name");
564
565 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.5.7.3.1", id_kp_serverAuth,
566 "id-kp-serverAuth EKU", "Server Authentication EKU");
567
568 /* Success */
569 retval = 0;
570
571 pkinit_oids_refs++;
572 /* Solaris Kerberos */
573 k5_mutex_unlock(&oids_mutex);
574
575 out:
576 return retval;
577 }
578
579 static krb5_error_code
580 get_cert(char *filename, X509 **retcert)
581 {
582 X509 *cert = NULL;
583 BIO *tmp = NULL;
584 int code;
585 krb5_error_code retval;
586
587 if (filename == NULL || retcert == NULL)
588 return EINVAL;
589
590 *retcert = NULL;
591
592 tmp = BIO_new(BIO_s_file());
593 if (tmp == NULL)
594 return ENOMEM;
595
596 code = BIO_read_filename(tmp, filename);
635 }
636 pkey = (EVP_PKEY *) PEM_read_bio_PrivateKey(tmp, NULL, NULL, NULL);
637 if (pkey == NULL) {
638 retval = EIO;
639 pkiDebug("failed to read private key from %s\n", filename);
640 goto cleanup;
641 }
642 *retkey = pkey;
643 retval = 0;
644 cleanup:
645 if (tmp != NULL)
646 BIO_free(tmp);
647 return retval;
648 }
649
650 static void
651 pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
652 {
653 if (ctx == NULL)
654 return;
655
656 /* Only call OBJ_cleanup once! */
657 /* Solaris Kerberos: locking */
658 k5_mutex_lock(&oids_mutex);
659 if (--pkinit_oids_refs == 0)
660 OBJ_cleanup();
661 k5_mutex_unlock(&oids_mutex);
662 }
663
664 static krb5_error_code
665 pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
666 {
667 krb5_error_code retval = ENOMEM;
668
669 plgctx->dh_1024 = DH_new();
670 if (plgctx->dh_1024 == NULL)
671 goto cleanup;
672 plgctx->dh_1024->p = BN_bin2bn(pkinit_1024_dhprime,
673 sizeof(pkinit_1024_dhprime), NULL);
674 if ((plgctx->dh_1024->g = BN_new()) == NULL ||
675 (plgctx->dh_1024->q = BN_new()) == NULL)
676 goto cleanup;
677 BN_set_word(plgctx->dh_1024->g, DH_GENERATOR_2);
678 BN_rshift1(plgctx->dh_1024->q, plgctx->dh_1024->p);
679
680 plgctx->dh_2048 = DH_new();
681 if (plgctx->dh_2048 == NULL)
819 if (ctx->cert_label != NULL)
820 free(ctx->cert_label);
821 if (ctx->PIN != NULL) {
822 (void) memset(ctx->PIN, 0, strlen(ctx->PIN));
823 free(ctx->PIN);
824 }
825 #endif
826 }
827
828 krb5_error_code
829 pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx,
830 krb5_prompter_fct prompter,
831 void *prompter_data)
832 {
833 id_cryptoctx->prompter = prompter;
834 id_cryptoctx->prompter_data = prompter_data;
835
836 return 0;
837 }
838
839 /* ARGSUSED */
840 krb5_error_code
841 cms_signeddata_create(krb5_context context,
842 pkinit_plg_crypto_context plg_cryptoctx,
843 pkinit_req_crypto_context req_cryptoctx,
844 pkinit_identity_crypto_context id_cryptoctx,
845 int cms_msg_type,
846 int include_certchain,
847 unsigned char *data,
848 unsigned int data_len,
849 unsigned char **signed_data,
850 unsigned int *signed_data_len)
851 {
852 /* Solaris Kerberos */
853 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
854 PKCS7 *p7 = NULL, *inner_p7 = NULL;
855 PKCS7_SIGNED *p7s = NULL;
856 PKCS7_SIGNER_INFO *p7si = NULL;
857 unsigned char *p;
858 ASN1_TYPE *pkinit_data = NULL;
859 STACK_OF(X509) * cert_stack = NULL;
860 ASN1_OCTET_STRING *digest_attr = NULL;
861 EVP_MD_CTX ctx, ctx2;
862 const EVP_MD *md_tmp = NULL;
863 unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE];
864 unsigned char *digestInfo_buf = NULL, *abuf = NULL;
865 unsigned int md_len, md_len2, alen, digestInfo_len;
866 STACK_OF(X509_ATTRIBUTE) * sk;
867 unsigned char *sig = NULL;
868 unsigned int sig_len = 0;
869 X509_ALGOR *alg = NULL;
870 ASN1_OCTET_STRING *digest = NULL;
871 unsigned int alg_len = 0, digest_len = 0;
872 unsigned char *y = NULL, *alg_buf = NULL, *digest_buf = NULL;
873 X509 *cert = NULL;
874 ASN1_OBJECT *oid = NULL;
875
876 /* Solaris Kerberos */
877 if (signed_data == NULL)
878 return EINVAL;
879
880 if (signed_data_len == NULL)
881 return EINVAL;
882
883 /* start creating PKCS7 data */
884 if ((p7 = PKCS7_new()) == NULL)
885 goto cleanup;
886 p7->type = OBJ_nid2obj(NID_pkcs7_signed);
887
888 if ((p7s = PKCS7_SIGNED_new()) == NULL)
889 goto cleanup;
890 p7->d.sign = p7s;
891 if (!ASN1_INTEGER_set(p7s->version, 3))
892 goto cleanup;
893
894 /* create a cert chain that has at least the signer's certificate */
979 if (cms_msg_type == CMS_SIGN_DRAFT9) {
980 /* don't include signed attributes for pa-type 15 request */
981 abuf = data;
982 alen = data_len;
983 } else {
984 /* add signed attributes */
985 /* compute sha1 digest over the EncapsulatedContentInfo */
986 EVP_MD_CTX_init(&ctx);
987 EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
988 EVP_DigestUpdate(&ctx, data, data_len);
989 md_tmp = EVP_MD_CTX_md(&ctx);
990 EVP_DigestFinal_ex(&ctx, md_data, &md_len);
991
992 /* create a message digest attr */
993 digest_attr = ASN1_OCTET_STRING_new();
994 ASN1_OCTET_STRING_set(digest_attr, md_data, (int)md_len);
995 PKCS7_add_signed_attribute(p7si, NID_pkcs9_messageDigest,
996 V_ASN1_OCTET_STRING, (char *) digest_attr);
997
998 /* create a content-type attr */
999 PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
1000 V_ASN1_OBJECT, oid);
1001
1002 /* create the signature over signed attributes. get DER encoded value */
1003 /* This is the place where smartcard signature needs to be calculated */
1004 sk = p7si->auth_attr;
1005 alen = ASN1_item_i2d((ASN1_VALUE *) sk, &abuf,
1006 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
1007 if (abuf == NULL)
1008 goto cleanup2;
1009 }
1010
1011 #ifndef WITHOUT_PKCS11
1012 /* Some tokens can only do RSAEncryption without sha1 hash */
1013 /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
1014 * function and the hash value into an ASN.1 value of type DigestInfo
1015 * DigestInfo::=SEQUENCE {
1016 * digestAlgorithm AlgorithmIdentifier,
1017 * digest OCTET STRING }
1018 */
1019 if (id_cryptoctx->pkcs11_method == 1 &&
1020 id_cryptoctx->mech == CKM_RSA_PKCS) {
1077 if (cms_msg_type != CMS_SIGN_DRAFT9)
1078 free(abuf);
1079 if (retval)
1080 goto cleanup2;
1081
1082 /* Add signature */
1083 if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig,
1084 (int)sig_len)) {
1085 unsigned long err = ERR_peek_error();
1086 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1087 krb5_set_error_message(context, retval, "%s\n",
1088 ERR_error_string(err, NULL));
1089 pkiDebug("failed to add a signed digest attribute\n");
1090 goto cleanup2;
1091 }
1092 /* adder signer_info to pkcs7 signed */
1093 if (!PKCS7_add_signer(p7, p7si))
1094 goto cleanup2;
1095
1096 /* start on adding data to the pkcs7 signed */
1097 if ((inner_p7 = PKCS7_new()) == NULL)
1098 goto cleanup2;
1099 if ((pkinit_data = ASN1_TYPE_new()) == NULL)
1100 goto cleanup2;
1101 pkinit_data->type = V_ASN1_OCTET_STRING;
1102 if ((pkinit_data->value.octet_string = ASN1_OCTET_STRING_new()) == NULL)
1103 goto cleanup2;
1104 if (!ASN1_OCTET_STRING_set(pkinit_data->value.octet_string, data,
1105 (int)data_len)) {
1106 unsigned long err = ERR_peek_error();
1107 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1108 krb5_set_error_message(context, retval, "%s\n",
1109 ERR_error_string(err, NULL));
1110 pkiDebug("failed to add pkcs7 data\n");
1111 goto cleanup2;
1112 }
1113
1114 if (!PKCS7_set0_type_other(inner_p7, OBJ_obj2nid(oid), pkinit_data))
1115 goto cleanup2;
1116
1117 if (p7s->contents != NULL)
1118 PKCS7_free(p7s->contents);
1119 p7s->contents = inner_p7;
1120
1121 *signed_data_len = i2d_PKCS7(p7, NULL);
1122 if (!(*signed_data_len)) {
1123 unsigned long err = ERR_peek_error();
1124 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1125 krb5_set_error_message(context, retval, "%s\n",
1126 ERR_error_string(err, NULL));
1127 pkiDebug("failed to der encode pkcs7\n");
1128 goto cleanup2;
1129 }
1130 if ((p = *signed_data =
1131 (unsigned char *) malloc((size_t)*signed_data_len)) == NULL)
1132 goto cleanup2;
1133
1134 /* DER encode PKCS7 data */
1135 retval = i2d_PKCS7(p7, &p);
1136 if (!retval) {
1207 unsigned int vflags = 0, size = 0;
1208 const unsigned char *p = signed_data;
1209 STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
1210 PKCS7_SIGNER_INFO *si = NULL;
1211 X509 *x = NULL;
1212 X509_STORE *store = NULL;
1213 X509_STORE_CTX cert_ctx;
1214 STACK_OF(X509) *intermediateCAs = NULL;
1215 STACK_OF(X509_CRL) *revoked = NULL;
1216 STACK_OF(X509) *verified_chain = NULL;
1217 ASN1_OBJECT *oid = NULL;
1218 krb5_external_principal_identifier **krb5_verified_chain = NULL;
1219 krb5_data *authz = NULL;
1220 char buf[DN_BUF_LEN];
1221
1222 #ifdef DEBUG_ASN1
1223 print_buffer_bin(signed_data, signed_data_len,
1224 "/tmp/client_received_pkcs7_signeddata");
1225 #endif
1226
1227 /* Do this early enough to create the shadow OID for pkcs7-data if needed */
1228 oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type);
1229 if (oid == NULL)
1230 goto cleanup;
1231
1232 /* decode received PKCS7 message */
1233 if ((p7 = d2i_PKCS7(NULL, &p, (int)signed_data_len)) == NULL) {
1234 unsigned long err = ERR_peek_error();
1235 krb5_set_error_message(context, retval, "%s\n",
1236 ERR_error_string(err, NULL));
1237 pkiDebug("%s: failed to decode message: %s\n",
1238 __FUNCTION__, ERR_error_string(err, NULL));
1239 goto cleanup;
1240 }
1241
1242 /* verify that the received message is PKCS7 SignedData message */
1243 if (OBJ_obj2nid(p7->type) != NID_pkcs7_signed) {
1244 pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n",
1245 OBJ_obj2nid(p7->type));
1246 krb5_set_error_message(context, retval, "wrong oid\n");
1247 goto cleanup;
3110 return ok;
3111 }
3112
3113 static int
3114 openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx)
3115 {
3116 if (!ok) {
3117 switch (ctx->error) {
3118 case X509_V_ERR_UNABLE_TO_GET_CRL:
3119 return 1;
3120 default:
3121 return 0;
3122 }
3123 }
3124 return ok;
3125 }
3126
3127 static ASN1_OBJECT *
3128 pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
3129 {
3130 int nid;
3131
3132 switch (pkcs7_type) {
3133 case CMS_SIGN_CLIENT:
3134 return cryptoctx->id_pkinit_authData;
3135 case CMS_SIGN_DRAFT9:
3136 /*
3137 * Delay creating this OID until we know we need it.
3138 * It shadows an existing OpenSSL oid. If it
3139 * is created too early, it breaks things like
3140 * the use of pkcs12 (which uses pkcs7 structures).
3141 * We need this shadow version because our code
3142 * depends on the "other" type to be unknown to the
3143 * OpenSSL code.
3144 */
3145 if (cryptoctx->id_pkinit_authData9 == NULL) {
3146 pkiDebug("%s: Creating shadow instance of pkcs7-data oid\n",
3147 __FUNCTION__);
3148 nid = OBJ_create("1.2.840.113549.1.7.1", "id-pkcs7-data",
3149 "PKCS7 data");
3150 if (nid == NID_undef)
3151 return NULL;
3152 cryptoctx->id_pkinit_authData9 = OBJ_nid2obj(nid);
3153 }
3154 return cryptoctx->id_pkinit_authData9;
3155 case CMS_SIGN_SERVER:
3156 return cryptoctx->id_pkinit_DHKeyData;
3157 case CMS_ENVEL_SERVER:
3158 return cryptoctx->id_pkinit_rkeyData;
3159 default:
3160 return NULL;
3161 }
3162
3163 }
3164
3165 #ifdef LONGHORN_BETA_COMPAT
3166 #if 0
3167 /*
3168 * This is a version that worked with Longhorn Beta 3.
3169 */
3170 static int
3171 wrap_signeddata(unsigned char *data, unsigned int data_len,
3172 unsigned char **out, unsigned int *out_len,
3173 int is_longhorn_server)
3174 {
|
14 * portion of this software, then the disclaimer below must
15 * also be included.
16 *
17 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGES.
29 */
30
31 /*
32 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
33 * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
34 * Copyright 2017 RackTop Systems.
35 */
36
37 #include <errno.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <dlfcn.h>
42 #include <unistd.h>
43 #include <dirent.h>
44
45
46 /* Solaris Kerberos */
47 #include <libintl.h>
48 #include <assert.h>
49 #include <security/pam_appl.h>
50 #include <ctype.h>
51 #include "k5-int.h"
52 #include <ctype.h>
53
54 /*
353 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
354 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
355 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
356 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
357 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
358 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
359 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
360 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
361 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
362 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
363 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
364 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
365 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
366 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
367 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
368 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
369 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
370 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
371 };
372
373 krb5_error_code
374 pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx) {
375
376 krb5_error_code retval = ENOMEM;
377 pkinit_plg_crypto_context ctx = NULL;
378
379 /* initialize openssl routines */
380 /* Solaris Kerberos */
381 retval = openssl_init();
382 if (retval != 0)
383 goto out;
384
385 ctx = (pkinit_plg_crypto_context)malloc(sizeof(*ctx));
386 if (ctx == NULL)
387 goto out;
388 (void) memset(ctx, 0, sizeof(*ctx));
389
390 pkiDebug("%s: initializing openssl crypto context at %p\n",
391 __FUNCTION__, ctx);
392 retval = pkinit_init_pkinit_oids(ctx);
487 }
488
489 void
490 pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)
491 {
492 if (req_cryptoctx == NULL)
493 return;
494
495 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, req_cryptoctx);
496 if (req_cryptoctx->dh != NULL)
497 DH_free(req_cryptoctx->dh);
498 if (req_cryptoctx->received_cert != NULL)
499 X509_free(req_cryptoctx->received_cert);
500
501 free(req_cryptoctx);
502 }
503
504 static krb5_error_code
505 pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)
506 {
507 ctx->id_pkinit_san = OBJ_txt2obj("1.3.6.1.5.2.2", 1);
508 if (ctx->id_pkinit_san == NULL)
509 return ENOMEM;
510
511 ctx->id_pkinit_authData = OBJ_txt2obj("1.3.6.1.5.2.3.1", 1);
512 if (ctx->id_pkinit_authData == NULL)
513 return ENOMEM;
514
515 ctx->id_pkinit_DHKeyData = OBJ_txt2obj("1.3.6.1.5.2.3.2", 1);
516 if (ctx->id_pkinit_DHKeyData == NULL)
517 return ENOMEM;
518
519 ctx->id_pkinit_rkeyData = OBJ_txt2obj("1.3.6.1.5.2.3.3", 1);
520 if (ctx->id_pkinit_rkeyData == NULL)
521 return ENOMEM;
522
523 ctx->id_pkinit_KPClientAuth = OBJ_txt2obj("1.3.6.1.5.2.3.4", 1);
524 if (ctx->id_pkinit_KPClientAuth == NULL)
525 return ENOMEM;
526
527 ctx->id_pkinit_KPKdc = OBJ_txt2obj("1.3.6.1.5.2.3.5", 1);
528 if (ctx->id_pkinit_KPKdc == NULL)
529 return ENOMEM;
530
531 ctx->id_ms_kp_sc_logon = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.2", 1);
532 if (ctx->id_ms_kp_sc_logon == NULL)
533 return ENOMEM;
534
535 ctx->id_ms_san_upn = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 1);
536 if (ctx->id_ms_san_upn == NULL)
537 return ENOMEM;
538
539 ctx->id_kp_serverAuth = OBJ_txt2obj("1.3.6.1.5.5.7.3.1", 1);
540 if (ctx->id_kp_serverAuth == NULL)
541 return ENOMEM;
542
543 return 0;
544 }
545
546 static krb5_error_code
547 get_cert(char *filename, X509 **retcert)
548 {
549 X509 *cert = NULL;
550 BIO *tmp = NULL;
551 int code;
552 krb5_error_code retval;
553
554 if (filename == NULL || retcert == NULL)
555 return EINVAL;
556
557 *retcert = NULL;
558
559 tmp = BIO_new(BIO_s_file());
560 if (tmp == NULL)
561 return ENOMEM;
562
563 code = BIO_read_filename(tmp, filename);
602 }
603 pkey = (EVP_PKEY *) PEM_read_bio_PrivateKey(tmp, NULL, NULL, NULL);
604 if (pkey == NULL) {
605 retval = EIO;
606 pkiDebug("failed to read private key from %s\n", filename);
607 goto cleanup;
608 }
609 *retkey = pkey;
610 retval = 0;
611 cleanup:
612 if (tmp != NULL)
613 BIO_free(tmp);
614 return retval;
615 }
616
617 static void
618 pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
619 {
620 if (ctx == NULL)
621 return;
622 ASN1_OBJECT_free(ctx->id_pkinit_san);
623 ASN1_OBJECT_free(ctx->id_pkinit_authData);
624 ASN1_OBJECT_free(ctx->id_pkinit_DHKeyData);
625 ASN1_OBJECT_free(ctx->id_pkinit_rkeyData);
626 ASN1_OBJECT_free(ctx->id_pkinit_KPClientAuth);
627 ASN1_OBJECT_free(ctx->id_pkinit_KPKdc);
628 ASN1_OBJECT_free(ctx->id_ms_kp_sc_logon);
629 ASN1_OBJECT_free(ctx->id_ms_san_upn);
630 ASN1_OBJECT_free(ctx->id_kp_serverAuth);
631 }
632
633 static krb5_error_code
634 pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
635 {
636 krb5_error_code retval = ENOMEM;
637
638 plgctx->dh_1024 = DH_new();
639 if (plgctx->dh_1024 == NULL)
640 goto cleanup;
641 plgctx->dh_1024->p = BN_bin2bn(pkinit_1024_dhprime,
642 sizeof(pkinit_1024_dhprime), NULL);
643 if ((plgctx->dh_1024->g = BN_new()) == NULL ||
644 (plgctx->dh_1024->q = BN_new()) == NULL)
645 goto cleanup;
646 BN_set_word(plgctx->dh_1024->g, DH_GENERATOR_2);
647 BN_rshift1(plgctx->dh_1024->q, plgctx->dh_1024->p);
648
649 plgctx->dh_2048 = DH_new();
650 if (plgctx->dh_2048 == NULL)
788 if (ctx->cert_label != NULL)
789 free(ctx->cert_label);
790 if (ctx->PIN != NULL) {
791 (void) memset(ctx->PIN, 0, strlen(ctx->PIN));
792 free(ctx->PIN);
793 }
794 #endif
795 }
796
797 krb5_error_code
798 pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx,
799 krb5_prompter_fct prompter,
800 void *prompter_data)
801 {
802 id_cryptoctx->prompter = prompter;
803 id_cryptoctx->prompter_data = prompter_data;
804
805 return 0;
806 }
807
808 /* Create a CMS ContentInfo of type oid containing the octet string in data. */
809 static krb5_error_code
810 create_contentinfo(krb5_context context,
811 ASN1_OBJECT *oid,
812 unsigned char *data,
813 size_t data_len,
814 PKCS7 **p7_out)
815 {
816 PKCS7 *p7 = NULL;
817 ASN1_OCTET_STRING *ostr = NULL;
818
819 *p7_out = NULL;
820
821 ostr = ASN1_OCTET_STRING_new();
822 if (ostr == NULL)
823 goto oom;
824 if (!ASN1_OCTET_STRING_set(ostr, (unsigned char *)data, data_len))
825 goto oom;
826
827 p7 = PKCS7_new();
828 if (p7 == NULL)
829 goto oom;
830 p7->type = OBJ_dup(oid);
831 if (p7->type == NULL)
832 goto oom;
833
834 if (OBJ_obj2nid(oid) == NID_pkcs7_data) {
835 /* Draft 9 uses id-pkcs7-data for signed data. For this type OpenSSL
836 * expects an octet string in d.data. */
837 p7->d.data = ostr;
838 } else {
839 p7->d.other = ASN1_TYPE_new();
840 if (p7->d.other == NULL)
841 goto oom;
842 p7->d.other->type = V_ASN1_OCTET_STRING;
843 p7->d.other->value.octet_string = ostr;
844 }
845
846 *p7_out = p7;
847 return 0;
848
849 oom:
850 if (ostr != NULL)
851 ASN1_OCTET_STRING_free(ostr);
852 if (p7 != NULL)
853 PKCS7_free(p7);
854 return ENOMEM;
855 }
856
857 /* ARGSUSED */
858 krb5_error_code
859 cms_signeddata_create(krb5_context context,
860 pkinit_plg_crypto_context plg_cryptoctx,
861 pkinit_req_crypto_context req_cryptoctx,
862 pkinit_identity_crypto_context id_cryptoctx,
863 int cms_msg_type,
864 int include_certchain,
865 unsigned char *data,
866 unsigned int data_len,
867 unsigned char **signed_data,
868 unsigned int *signed_data_len)
869 {
870 /* Solaris Kerberos */
871 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
872 PKCS7 *p7 = NULL, *inner_p7 = NULL;
873 PKCS7_SIGNED *p7s = NULL;
874 PKCS7_SIGNER_INFO *p7si = NULL;
875 unsigned char *p;
876 STACK_OF(X509) * cert_stack = NULL;
877 ASN1_OCTET_STRING *digest_attr = NULL;
878 EVP_MD_CTX ctx, ctx2;
879 const EVP_MD *md_tmp = NULL;
880 unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE];
881 unsigned char *digestInfo_buf = NULL, *abuf = NULL;
882 unsigned int md_len, md_len2, alen, digestInfo_len;
883 STACK_OF(X509_ATTRIBUTE) * sk;
884 unsigned char *sig = NULL;
885 unsigned int sig_len = 0;
886 X509_ALGOR *alg = NULL;
887 ASN1_OCTET_STRING *digest = NULL;
888 unsigned int alg_len = 0, digest_len = 0;
889 unsigned char *y = NULL, *alg_buf = NULL, *digest_buf = NULL;
890 X509 *cert = NULL;
891 ASN1_OBJECT *oid = NULL, *oid_copy;
892
893 /* Solaris Kerberos */
894 if (signed_data == NULL)
895 return EINVAL;
896
897 if (signed_data_len == NULL)
898 return EINVAL;
899
900 /* start creating PKCS7 data */
901 if ((p7 = PKCS7_new()) == NULL)
902 goto cleanup;
903 p7->type = OBJ_nid2obj(NID_pkcs7_signed);
904
905 if ((p7s = PKCS7_SIGNED_new()) == NULL)
906 goto cleanup;
907 p7->d.sign = p7s;
908 if (!ASN1_INTEGER_set(p7s->version, 3))
909 goto cleanup;
910
911 /* create a cert chain that has at least the signer's certificate */
996 if (cms_msg_type == CMS_SIGN_DRAFT9) {
997 /* don't include signed attributes for pa-type 15 request */
998 abuf = data;
999 alen = data_len;
1000 } else {
1001 /* add signed attributes */
1002 /* compute sha1 digest over the EncapsulatedContentInfo */
1003 EVP_MD_CTX_init(&ctx);
1004 EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
1005 EVP_DigestUpdate(&ctx, data, data_len);
1006 md_tmp = EVP_MD_CTX_md(&ctx);
1007 EVP_DigestFinal_ex(&ctx, md_data, &md_len);
1008
1009 /* create a message digest attr */
1010 digest_attr = ASN1_OCTET_STRING_new();
1011 ASN1_OCTET_STRING_set(digest_attr, md_data, (int)md_len);
1012 PKCS7_add_signed_attribute(p7si, NID_pkcs9_messageDigest,
1013 V_ASN1_OCTET_STRING, (char *) digest_attr);
1014
1015 /* create a content-type attr */
1016 oid_copy = OBJ_dup(oid);
1017 if (oid_copy == NULL)
1018 goto cleanup2;
1019 PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
1020 V_ASN1_OBJECT, oid_copy);
1021
1022 /* create the signature over signed attributes. get DER encoded value */
1023 /* This is the place where smartcard signature needs to be calculated */
1024 sk = p7si->auth_attr;
1025 alen = ASN1_item_i2d((ASN1_VALUE *) sk, &abuf,
1026 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
1027 if (abuf == NULL)
1028 goto cleanup2;
1029 }
1030
1031 #ifndef WITHOUT_PKCS11
1032 /* Some tokens can only do RSAEncryption without sha1 hash */
1033 /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
1034 * function and the hash value into an ASN.1 value of type DigestInfo
1035 * DigestInfo::=SEQUENCE {
1036 * digestAlgorithm AlgorithmIdentifier,
1037 * digest OCTET STRING }
1038 */
1039 if (id_cryptoctx->pkcs11_method == 1 &&
1040 id_cryptoctx->mech == CKM_RSA_PKCS) {
1097 if (cms_msg_type != CMS_SIGN_DRAFT9)
1098 free(abuf);
1099 if (retval)
1100 goto cleanup2;
1101
1102 /* Add signature */
1103 if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig,
1104 (int)sig_len)) {
1105 unsigned long err = ERR_peek_error();
1106 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1107 krb5_set_error_message(context, retval, "%s\n",
1108 ERR_error_string(err, NULL));
1109 pkiDebug("failed to add a signed digest attribute\n");
1110 goto cleanup2;
1111 }
1112 /* adder signer_info to pkcs7 signed */
1113 if (!PKCS7_add_signer(p7, p7si))
1114 goto cleanup2;
1115
1116 /* start on adding data to the pkcs7 signed */
1117 retval = create_contentinfo(context, oid, data, data_len, &inner_p7);
1118 if (p7s->contents != NULL)
1119 PKCS7_free(p7s->contents);
1120 p7s->contents = inner_p7;
1121
1122 *signed_data_len = i2d_PKCS7(p7, NULL);
1123 if (!(*signed_data_len)) {
1124 unsigned long err = ERR_peek_error();
1125 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1126 krb5_set_error_message(context, retval, "%s\n",
1127 ERR_error_string(err, NULL));
1128 pkiDebug("failed to der encode pkcs7\n");
1129 goto cleanup2;
1130 }
1131 if ((p = *signed_data =
1132 (unsigned char *) malloc((size_t)*signed_data_len)) == NULL)
1133 goto cleanup2;
1134
1135 /* DER encode PKCS7 data */
1136 retval = i2d_PKCS7(p7, &p);
1137 if (!retval) {
1208 unsigned int vflags = 0, size = 0;
1209 const unsigned char *p = signed_data;
1210 STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
1211 PKCS7_SIGNER_INFO *si = NULL;
1212 X509 *x = NULL;
1213 X509_STORE *store = NULL;
1214 X509_STORE_CTX cert_ctx;
1215 STACK_OF(X509) *intermediateCAs = NULL;
1216 STACK_OF(X509_CRL) *revoked = NULL;
1217 STACK_OF(X509) *verified_chain = NULL;
1218 ASN1_OBJECT *oid = NULL;
1219 krb5_external_principal_identifier **krb5_verified_chain = NULL;
1220 krb5_data *authz = NULL;
1221 char buf[DN_BUF_LEN];
1222
1223 #ifdef DEBUG_ASN1
1224 print_buffer_bin(signed_data, signed_data_len,
1225 "/tmp/client_received_pkcs7_signeddata");
1226 #endif
1227
1228 oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type);
1229 if (oid == NULL)
1230 goto cleanup;
1231
1232 /* decode received PKCS7 message */
1233 if ((p7 = d2i_PKCS7(NULL, &p, (int)signed_data_len)) == NULL) {
1234 unsigned long err = ERR_peek_error();
1235 krb5_set_error_message(context, retval, "%s\n",
1236 ERR_error_string(err, NULL));
1237 pkiDebug("%s: failed to decode message: %s\n",
1238 __FUNCTION__, ERR_error_string(err, NULL));
1239 goto cleanup;
1240 }
1241
1242 /* verify that the received message is PKCS7 SignedData message */
1243 if (OBJ_obj2nid(p7->type) != NID_pkcs7_signed) {
1244 pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n",
1245 OBJ_obj2nid(p7->type));
1246 krb5_set_error_message(context, retval, "wrong oid\n");
1247 goto cleanup;
3110 return ok;
3111 }
3112
3113 static int
3114 openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx)
3115 {
3116 if (!ok) {
3117 switch (ctx->error) {
3118 case X509_V_ERR_UNABLE_TO_GET_CRL:
3119 return 1;
3120 default:
3121 return 0;
3122 }
3123 }
3124 return ok;
3125 }
3126
3127 static ASN1_OBJECT *
3128 pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
3129 {
3130 switch (pkcs7_type) {
3131 case CMS_SIGN_CLIENT:
3132 return cryptoctx->id_pkinit_authData;
3133 case CMS_SIGN_DRAFT9:
3134 return OBJ_nid2obj(NID_pkcs7_data);
3135 case CMS_SIGN_SERVER:
3136 return cryptoctx->id_pkinit_DHKeyData;
3137 case CMS_ENVEL_SERVER:
3138 return cryptoctx->id_pkinit_rkeyData;
3139 default:
3140 return NULL;
3141 }
3142
3143 }
3144
3145 #ifdef LONGHORN_BETA_COMPAT
3146 #if 0
3147 /*
3148 * This is a version that worked with Longhorn Beta 3.
3149 */
3150 static int
3151 wrap_signeddata(unsigned char *data, unsigned int data_len,
3152 unsigned char **out, unsigned int *out_len,
3153 int is_longhorn_server)
3154 {
|