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