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