1 /* 2 * COPYRIGHT (C) 2006,2007 3 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN 4 * ALL RIGHTS RESERVED 5 * 6 * Permission is granted to use, copy, create derivative works 7 * and redistribute this software and such derivative works 8 * for any purpose, so long as the name of The University of 9 * Michigan is not used in any advertising or publicity 10 * pertaining to the use of distribution of this software 11 * without specific, written prior authorization. If the 12 * above copyright notice or any other identification of the 13 * University of Michigan is included in any copy of any 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 2018 OmniOS Community Edition (OmniOSce) Association. 34 * Copyright 2018 RackTop Systems. 35 */ 36 37 #ifndef _PKINIT_CRYPTO_OPENSSL_H 38 #define _PKINIT_CRYPTO_OPENSSL_H 39 40 #include <openssl/bn.h> 41 #include <openssl/dh.h> 42 #include <openssl/x509.h> 43 #include <openssl/pkcs7.h> 44 #include <openssl/pkcs12.h> 45 #include <openssl/obj_mac.h> 46 #include <openssl/x509v3.h> 47 #include <openssl/err.h> 48 #include <openssl/evp.h> 49 #include <openssl/sha.h> 50 #include <openssl/asn1.h> 51 #include <openssl/pem.h> 52 #include <openssl/rsa.h> 53 54 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 55 #include <openssl/asn1_mac.h> 56 #else 57 #include <openssl/asn1t.h> 58 #endif 59 60 #include "pkinit.h" 61 62 #define DN_BUF_LEN 256 63 #define MAX_CREDS_ALLOWED 20 64 65 struct _pkinit_cred_info { 66 X509 *cert; 67 EVP_PKEY *key; 68 #ifndef WITHOUT_PKCS11 69 CK_BYTE_PTR cert_id; 70 int cert_id_len; 71 #endif 72 }; 73 typedef struct _pkinit_cred_info * pkinit_cred_info; 74 75 struct _pkinit_identity_crypto_context { 76 pkinit_cred_info creds[MAX_CREDS_ALLOWED+1]; 77 STACK_OF(X509) *my_certs; /* available user certs */ 78 int cert_index; /* cert to use out of available certs*/ 79 EVP_PKEY *my_key; /* available user keys if in filesystem */ 80 STACK_OF(X509) *trustedCAs; /* available trusted ca certs */ 81 STACK_OF(X509) *intermediateCAs; /* available intermediate ca certs */ 82 STACK_OF(X509_CRL) *revoked; /* available crls */ 83 int pkcs11_method; 84 krb5_prompter_fct prompter; 85 void *prompter_data; 86 #ifndef WITHOUT_PKCS11 87 char *p11_module_name; 88 CK_SLOT_ID slotid; 89 char *token_label; 90 char *cert_label; 91 char *PIN; /* Solaris Kerberos: */ 92 /* These are crypto-specific */ 93 void *p11_module; 94 CK_SESSION_HANDLE session; 95 CK_FUNCTION_LIST_PTR p11; 96 CK_BYTE_PTR cert_id; 97 int cert_id_len; 98 CK_MECHANISM_TYPE mech; 99 /* Solaris Kerberos: need to keep some state */ 100 uint_t p11flags; 101 /* 102 * Solaris Kerberos: 103 * If PKCS#11 is already being used by the process then C_Finalize should 104 * not be called by pkinit as it would invalidate any PKCS#11 sessions the 105 * process was using prior to loading the pkinit plugin. "finalize_pkcs11" 106 * indicates whether or not C_Finalize should be called by pkinit. 107 */ 108 krb5_boolean finalize_pkcs11; 109 #endif 110 }; 111 112 /* Solaris Kerberos: need to know if login was done */ 113 #define C_LOGIN_DONE 0x1 /* The session is logged in. */ 114 #define C_PROMPTED_USER 0x2 /* The user was prompted for token. */ 115 #define C_SKIP_PKCS11_AUTH 0x4 /* User does not want to do PKCS11 auth */ 116 117 struct _pkinit_plg_crypto_context { 118 DH *dh_1024; 119 DH *dh_2048; 120 DH *dh_4096; 121 ASN1_OBJECT *id_pkinit_authData; 122 ASN1_OBJECT *id_pkinit_DHKeyData; 123 ASN1_OBJECT *id_pkinit_rkeyData; 124 ASN1_OBJECT *id_pkinit_san; 125 ASN1_OBJECT *id_ms_san_upn; 126 ASN1_OBJECT *id_pkinit_KPClientAuth; 127 ASN1_OBJECT *id_pkinit_KPKdc; 128 ASN1_OBJECT *id_ms_kp_sc_logon; 129 ASN1_OBJECT *id_kp_serverAuth; 130 }; 131 132 struct _pkinit_req_crypto_context { 133 X509 *received_cert; 134 DH *dh; 135 }; 136 137 #define CERT_MAGIC 0x53534c43 138 struct _pkinit_cert_data { 139 unsigned int magic; 140 pkinit_plg_crypto_context plgctx; 141 pkinit_req_crypto_context reqctx; 142 pkinit_identity_crypto_context idctx; 143 pkinit_cred_info cred; 144 unsigned int index; /* Index of this cred in the creds[] array */ 145 }; 146 147 #define ITER_MAGIC 0x53534c49 148 struct _pkinit_cert_iter_data { 149 unsigned int magic; 150 pkinit_plg_crypto_context plgctx; 151 pkinit_req_crypto_context reqctx; 152 pkinit_identity_crypto_context idctx; 153 unsigned int index; 154 }; 155 156 /* Solaris Kerberos */ 157 static krb5_error_code openssl_init(void); 158 159 static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context ); 160 static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ); 161 162 static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context ); 163 static void pkinit_fini_dh_params(pkinit_plg_crypto_context ); 164 165 static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx); 166 static void pkinit_fini_certs(pkinit_identity_crypto_context ctx); 167 168 static krb5_error_code pkinit_init_pkcs11(pkinit_identity_crypto_context ctx); 169 static void pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx); 170 171 static krb5_error_code pkinit_encode_dh_params 172 (const BIGNUM *, const BIGNUM *, const BIGNUM *, 173 unsigned char **, unsigned int *); 174 static DH *pkinit_decode_dh_params 175 (DH **, unsigned char **, unsigned int ); 176 static int pkinit_check_dh_params 177 (const BIGNUM *p1, const BIGNUM *p2, const BIGNUM *g1, 178 const BIGNUM *q1); 179 180 static krb5_error_code pkinit_sign_data 181 (krb5_context context, pkinit_identity_crypto_context cryptoctx, 182 unsigned char *data, unsigned int data_len, 183 unsigned char **sig, unsigned int *sig_len); 184 185 static krb5_error_code create_signature 186 (unsigned char **, unsigned int *, unsigned char *, unsigned int, 187 EVP_PKEY *pkey); 188 189 static krb5_error_code pkinit_decode_data 190 (krb5_context context, pkinit_identity_crypto_context cryptoctx, 191 unsigned char *data, unsigned int data_len, 192 unsigned char **decoded, unsigned int *decoded_len); 193 194 static krb5_error_code decode_data 195 (unsigned char **, unsigned int *, unsigned char *, unsigned int, 196 EVP_PKEY *pkey, X509 *cert); 197 198 #ifdef DEBUG_DH 199 static void print_dh(DH *, char *); 200 static void print_pubkey(BIGNUM *, char *); 201 #endif 202 203 static int prepare_enc_data 204 (unsigned char *indata, int indata_len, unsigned char **outdata, 205 int *outdata_len); 206 207 static int openssl_callback (int, X509_STORE_CTX *); 208 static int openssl_callback_ignore_crls (int, X509_STORE_CTX *); 209 210 static int pkcs7_decrypt 211 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx, 212 PKCS7 *p7, BIO *bio); 213 214 static BIO * pkcs7_dataDecode 215 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx, 216 PKCS7 *p7); 217 218 static ASN1_OBJECT * pkinit_pkcs7type2oid 219 (pkinit_plg_crypto_context plg_cryptoctx, int pkcs7_type); 220 221 static krb5_error_code pkinit_create_sequence_of_principal_identifiers 222 (krb5_context context, pkinit_plg_crypto_context plg_cryptoctx, 223 pkinit_req_crypto_context req_cryptoctx, 224 pkinit_identity_crypto_context id_cryptoctx, 225 int type, krb5_data **out_data); 226 227 #ifndef WITHOUT_PKCS11 228 static krb5_error_code pkinit_find_private_key 229 (pkinit_identity_crypto_context, CK_ATTRIBUTE_TYPE usage, 230 CK_OBJECT_HANDLE *objp); 231 static krb5_error_code pkinit_login 232 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx, 233 CK_TOKEN_INFO *tip); 234 static void * pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p); 235 static CK_RV pkinit_C_UnloadModule(void *handle); 236 #ifdef SILLYDECRYPT 237 CK_RV pkinit_C_Decrypt 238 (pkinit_identity_crypto_context id_cryptoctx, 239 CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, 240 CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); 241 #endif 242 243 static krb5_error_code pkinit_sign_data_pkcs11 244 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx, 245 unsigned char *data, unsigned int data_len, 246 unsigned char **sig, unsigned int *sig_len); 247 static krb5_error_code pkinit_decode_data_pkcs11 248 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx, 249 unsigned char *data, unsigned int data_len, 250 unsigned char **decoded_data, unsigned int *decoded_data_len); 251 #endif /* WITHOUT_PKCS11 */ 252 253 static krb5_error_code pkinit_sign_data_fs 254 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx, 255 unsigned char *data, unsigned int data_len, 256 unsigned char **sig, unsigned int *sig_len); 257 static krb5_error_code pkinit_decode_data_fs 258 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx, 259 unsigned char *data, unsigned int data_len, 260 unsigned char **decoded_data, unsigned int *decoded_data_len); 261 262 static krb5_error_code der_decode_data 263 (unsigned char *, long, unsigned char **, long *); 264 265 static krb5_error_code 266 create_krb5_invalidCertificates(krb5_context context, 267 pkinit_plg_crypto_context plg_cryptoctx, 268 pkinit_req_crypto_context req_cryptoctx, 269 pkinit_identity_crypto_context id_cryptoctx, 270 krb5_external_principal_identifier *** ids); 271 272 static krb5_error_code 273 create_identifiers_from_stack(STACK_OF(X509) *sk, 274 krb5_external_principal_identifier *** ids); 275 #ifdef LONGHORN_BETA_COMPAT 276 static int 277 wrap_signeddata(unsigned char *data, unsigned int data_len, 278 unsigned char **out, unsigned int *out_len, 279 int is_longhorn_server); 280 #else 281 static int 282 wrap_signeddata(unsigned char *data, unsigned int data_len, 283 unsigned char **out, unsigned int *out_len); 284 #endif 285 286 /* This handy macro borrowed from crypto/x509v3/v3_purp.c */ 287 288 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 289 #define ku_reject(x, usage) \ 290 (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) 291 #else 292 #define ku_reject(x, usage) \ 293 ((X509_get_extension_flags(x) & EXFLAG_KUSAGE) && \ 294 !(X509_get_key_usage(x) & (usage))) 295 #endif 296 297 static char * 298 pkinit_pkcs11_code_to_text(int err); 299 300 #endif /* _PKINIT_CRYPTO_OPENSSL_H */ 301