1159d09a2SMark Phalan /*
2159d09a2SMark Phalan  * COPYRIGHT (C) 2006,2007
3159d09a2SMark Phalan  * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
4159d09a2SMark Phalan  * ALL RIGHTS RESERVED
5159d09a2SMark Phalan  *
6159d09a2SMark Phalan  * Permission is granted to use, copy, create derivative works
7159d09a2SMark Phalan  * and redistribute this software and such derivative works
8159d09a2SMark Phalan  * for any purpose, so long as the name of The University of
9159d09a2SMark Phalan  * Michigan is not used in any advertising or publicity
10159d09a2SMark Phalan  * pertaining to the use of distribution of this software
11159d09a2SMark Phalan  * without specific, written prior authorization.  If the
12159d09a2SMark Phalan  * above copyright notice or any other identification of the
13159d09a2SMark Phalan  * University of Michigan is included in any copy of any
14159d09a2SMark Phalan  * portion of this software, then the disclaimer below must
15159d09a2SMark Phalan  * also be included.
16159d09a2SMark Phalan  *
17159d09a2SMark Phalan  * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18159d09a2SMark Phalan  * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19159d09a2SMark Phalan  * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20159d09a2SMark Phalan  * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21159d09a2SMark Phalan  * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22159d09a2SMark Phalan  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23159d09a2SMark Phalan  * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24159d09a2SMark Phalan  * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25159d09a2SMark Phalan  * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26159d09a2SMark Phalan  * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27159d09a2SMark Phalan  * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
28159d09a2SMark Phalan  * SUCH DAMAGES.
29159d09a2SMark Phalan  */
30159d09a2SMark Phalan 
317d2d870eSWill Fiveash /*
3231a29035SMark Phalan  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
33300fdee2SAndy Fiddaman  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
34*553e44ceSAndrew Stormont  * Copyright 2018 RackTop Systems.
357d2d870eSWill Fiveash  */
367d2d870eSWill Fiveash 
37159d09a2SMark Phalan #ifndef _PKINIT_CRYPTO_OPENSSL_H
38159d09a2SMark Phalan #define _PKINIT_CRYPTO_OPENSSL_H
39159d09a2SMark Phalan 
40159d09a2SMark Phalan #include <openssl/bn.h>
41159d09a2SMark Phalan #include <openssl/dh.h>
42159d09a2SMark Phalan #include <openssl/x509.h>
43159d09a2SMark Phalan #include <openssl/pkcs7.h>
44159d09a2SMark Phalan #include <openssl/pkcs12.h>
45159d09a2SMark Phalan #include <openssl/obj_mac.h>
46159d09a2SMark Phalan #include <openssl/x509v3.h>
47159d09a2SMark Phalan #include <openssl/err.h>
48159d09a2SMark Phalan #include <openssl/evp.h>
49159d09a2SMark Phalan #include <openssl/sha.h>
50159d09a2SMark Phalan #include <openssl/asn1.h>
51159d09a2SMark Phalan #include <openssl/pem.h>
52300fdee2SAndy Fiddaman #include <openssl/rsa.h>
53300fdee2SAndy Fiddaman 
54*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
55300fdee2SAndy Fiddaman #include <openssl/asn1_mac.h>
56300fdee2SAndy Fiddaman #else
57300fdee2SAndy Fiddaman #include <openssl/asn1t.h>
58300fdee2SAndy Fiddaman #endif
59159d09a2SMark Phalan 
60159d09a2SMark Phalan #include "pkinit.h"
61159d09a2SMark Phalan 
62159d09a2SMark Phalan #define DN_BUF_LEN  256
63159d09a2SMark Phalan #define MAX_CREDS_ALLOWED 20
64159d09a2SMark Phalan 
65159d09a2SMark Phalan struct _pkinit_cred_info {
66159d09a2SMark Phalan     X509 *cert;
67159d09a2SMark Phalan     EVP_PKEY *key;
68159d09a2SMark Phalan #ifndef WITHOUT_PKCS11
69159d09a2SMark Phalan     CK_BYTE_PTR cert_id;
70159d09a2SMark Phalan     int cert_id_len;
71159d09a2SMark Phalan #endif
72159d09a2SMark Phalan };
73159d09a2SMark Phalan typedef struct _pkinit_cred_info * pkinit_cred_info;
74159d09a2SMark Phalan 
75159d09a2SMark Phalan struct _pkinit_identity_crypto_context {
76159d09a2SMark Phalan     pkinit_cred_info creds[MAX_CREDS_ALLOWED+1];
77159d09a2SMark Phalan     STACK_OF(X509) *my_certs;   /* available user certs */
78159d09a2SMark Phalan     int cert_index;             /* cert to use out of available certs*/
79159d09a2SMark Phalan     EVP_PKEY *my_key;           /* available user keys if in filesystem */
80159d09a2SMark Phalan     STACK_OF(X509) *trustedCAs; /* available trusted ca certs */
81159d09a2SMark Phalan     STACK_OF(X509) *intermediateCAs;   /* available intermediate ca certs */
82159d09a2SMark Phalan     STACK_OF(X509_CRL) *revoked;    /* available crls */
83159d09a2SMark Phalan     int pkcs11_method;
84159d09a2SMark Phalan     krb5_prompter_fct prompter;
85159d09a2SMark Phalan     void *prompter_data;
86159d09a2SMark Phalan #ifndef WITHOUT_PKCS11
87159d09a2SMark Phalan     char *p11_module_name;
88159d09a2SMark Phalan     CK_SLOT_ID slotid;
89159d09a2SMark Phalan     char *token_label;
90159d09a2SMark Phalan     char *cert_label;
91488060a6SWill Fiveash     char *PIN; /* Solaris Kerberos: */
92159d09a2SMark Phalan     /* These are crypto-specific */
93159d09a2SMark Phalan     void *p11_module;
94159d09a2SMark Phalan     CK_SESSION_HANDLE session;
95159d09a2SMark Phalan     CK_FUNCTION_LIST_PTR p11;
96159d09a2SMark Phalan     CK_BYTE_PTR cert_id;
97159d09a2SMark Phalan     int cert_id_len;
98159d09a2SMark Phalan     CK_MECHANISM_TYPE mech;
997d2d870eSWill Fiveash     /* Solaris Kerberos: need to keep some state */
1007d2d870eSWill Fiveash     uint_t p11flags;
101159d09a2SMark Phalan     /*
102159d09a2SMark Phalan      * Solaris Kerberos:
103159d09a2SMark Phalan      * If PKCS#11 is already being used by the process then C_Finalize should
104159d09a2SMark Phalan      * not be called by pkinit as it would invalidate any PKCS#11 sessions the
105159d09a2SMark Phalan      * process was using prior to loading the pkinit plugin. "finalize_pkcs11"
106159d09a2SMark Phalan      * indicates whether or not C_Finalize should be called by pkinit.
107159d09a2SMark Phalan      */
108159d09a2SMark Phalan     krb5_boolean finalize_pkcs11;
109159d09a2SMark Phalan #endif
110159d09a2SMark Phalan };
111159d09a2SMark Phalan 
1127d2d870eSWill Fiveash /* Solaris Kerberos: need to know if login was done */
1137d2d870eSWill Fiveash #define	C_LOGIN_DONE 0x1 /* The session is logged in. */
1149e11d51cSWill Fiveash #define	C_PROMPTED_USER 0x2 /* The user was prompted for token. */
1159e11d51cSWill Fiveash #define	C_SKIP_PKCS11_AUTH 0x4 /* User does not want to do PKCS11 auth */
1167d2d870eSWill Fiveash 
117159d09a2SMark Phalan struct _pkinit_plg_crypto_context {
118159d09a2SMark Phalan     DH *dh_1024;
119159d09a2SMark Phalan     DH *dh_2048;
120159d09a2SMark Phalan     DH *dh_4096;
121159d09a2SMark Phalan     ASN1_OBJECT *id_pkinit_authData;
122159d09a2SMark Phalan     ASN1_OBJECT *id_pkinit_DHKeyData;
123159d09a2SMark Phalan     ASN1_OBJECT *id_pkinit_rkeyData;
124159d09a2SMark Phalan     ASN1_OBJECT *id_pkinit_san;
125159d09a2SMark Phalan     ASN1_OBJECT *id_ms_san_upn;
126159d09a2SMark Phalan     ASN1_OBJECT *id_pkinit_KPClientAuth;
127159d09a2SMark Phalan     ASN1_OBJECT *id_pkinit_KPKdc;
128159d09a2SMark Phalan     ASN1_OBJECT *id_ms_kp_sc_logon;
129159d09a2SMark Phalan     ASN1_OBJECT *id_kp_serverAuth;
130159d09a2SMark Phalan };
131159d09a2SMark Phalan 
132159d09a2SMark Phalan struct _pkinit_req_crypto_context {
133159d09a2SMark Phalan     X509 *received_cert;
134159d09a2SMark Phalan     DH *dh;
135159d09a2SMark Phalan };
136159d09a2SMark Phalan 
137159d09a2SMark Phalan #define CERT_MAGIC 0x53534c43
138159d09a2SMark Phalan struct _pkinit_cert_data {
139159d09a2SMark Phalan     unsigned int magic;
140159d09a2SMark Phalan     pkinit_plg_crypto_context plgctx;
141159d09a2SMark Phalan     pkinit_req_crypto_context reqctx;
142159d09a2SMark Phalan     pkinit_identity_crypto_context idctx;
143159d09a2SMark Phalan     pkinit_cred_info cred;
144159d09a2SMark Phalan     unsigned int index;	    /* Index of this cred in the creds[] array */
145159d09a2SMark Phalan };
146159d09a2SMark Phalan 
147159d09a2SMark Phalan #define ITER_MAGIC 0x53534c49
148159d09a2SMark Phalan struct _pkinit_cert_iter_data {
149159d09a2SMark Phalan     unsigned int magic;
150159d09a2SMark Phalan     pkinit_plg_crypto_context plgctx;
151159d09a2SMark Phalan     pkinit_req_crypto_context reqctx;
152159d09a2SMark Phalan     pkinit_identity_crypto_context idctx;
153159d09a2SMark Phalan     unsigned int index;
154159d09a2SMark Phalan };
155159d09a2SMark Phalan 
15631a29035SMark Phalan /* Solaris Kerberos */
15731a29035SMark Phalan static krb5_error_code openssl_init(void);
158159d09a2SMark Phalan 
159159d09a2SMark Phalan static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
160159d09a2SMark Phalan static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
161159d09a2SMark Phalan 
162159d09a2SMark Phalan static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context );
163159d09a2SMark Phalan static void pkinit_fini_dh_params(pkinit_plg_crypto_context );
164159d09a2SMark Phalan 
165159d09a2SMark Phalan static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx);
166159d09a2SMark Phalan static void pkinit_fini_certs(pkinit_identity_crypto_context ctx);
167159d09a2SMark Phalan 
168159d09a2SMark Phalan static krb5_error_code pkinit_init_pkcs11(pkinit_identity_crypto_context ctx);
169159d09a2SMark Phalan static void pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx);
170159d09a2SMark Phalan 
171159d09a2SMark Phalan static krb5_error_code pkinit_encode_dh_params
172300fdee2SAndy Fiddaman 	(const BIGNUM *, const BIGNUM *, const BIGNUM *,
173300fdee2SAndy Fiddaman 		unsigned char **, unsigned int *);
174159d09a2SMark Phalan static DH *pkinit_decode_dh_params
175159d09a2SMark Phalan 	(DH **, unsigned char **, unsigned int );
176159d09a2SMark Phalan static int pkinit_check_dh_params
177300fdee2SAndy Fiddaman 	(const BIGNUM *p1, const BIGNUM *p2, const BIGNUM *g1,
178300fdee2SAndy Fiddaman 		const BIGNUM *q1);
179159d09a2SMark Phalan 
180159d09a2SMark Phalan static krb5_error_code pkinit_sign_data
181159d09a2SMark Phalan 	(krb5_context context, pkinit_identity_crypto_context cryptoctx,
182159d09a2SMark Phalan 		unsigned char *data, unsigned int data_len,
183159d09a2SMark Phalan 		unsigned char **sig, unsigned int *sig_len);
184159d09a2SMark Phalan 
185159d09a2SMark Phalan static krb5_error_code create_signature
186159d09a2SMark Phalan 	(unsigned char **, unsigned int *, unsigned char *, unsigned int,
187159d09a2SMark Phalan 		EVP_PKEY *pkey);
188159d09a2SMark Phalan 
189159d09a2SMark Phalan static krb5_error_code pkinit_decode_data
190159d09a2SMark Phalan 	(krb5_context context, pkinit_identity_crypto_context cryptoctx,
191159d09a2SMark Phalan 		unsigned char *data, unsigned int data_len,
192159d09a2SMark Phalan 		unsigned char **decoded, unsigned int *decoded_len);
193159d09a2SMark Phalan 
194159d09a2SMark Phalan static krb5_error_code decode_data
195159d09a2SMark Phalan 	(unsigned char **, unsigned int *, unsigned char *, unsigned int,
196159d09a2SMark Phalan 		EVP_PKEY *pkey, X509 *cert);
197159d09a2SMark Phalan 
198159d09a2SMark Phalan #ifdef DEBUG_DH
199159d09a2SMark Phalan static void print_dh(DH *, char *);
200159d09a2SMark Phalan static void print_pubkey(BIGNUM *, char *);
201159d09a2SMark Phalan #endif
202159d09a2SMark Phalan 
203159d09a2SMark Phalan static int prepare_enc_data
204159d09a2SMark Phalan 	(unsigned char *indata, int indata_len, unsigned char **outdata,
205159d09a2SMark Phalan 		int *outdata_len);
206159d09a2SMark Phalan 
207159d09a2SMark Phalan static int openssl_callback (int, X509_STORE_CTX *);
208159d09a2SMark Phalan static int openssl_callback_ignore_crls (int, X509_STORE_CTX *);
209159d09a2SMark Phalan 
210159d09a2SMark Phalan static int pkcs7_decrypt
211159d09a2SMark Phalan 	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
212159d09a2SMark Phalan 		PKCS7 *p7, BIO *bio);
213159d09a2SMark Phalan 
214159d09a2SMark Phalan static BIO * pkcs7_dataDecode
215159d09a2SMark Phalan 	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
216159d09a2SMark Phalan 		PKCS7 *p7);
217159d09a2SMark Phalan 
218159d09a2SMark Phalan static ASN1_OBJECT * pkinit_pkcs7type2oid
219159d09a2SMark Phalan 	(pkinit_plg_crypto_context plg_cryptoctx, int pkcs7_type);
220159d09a2SMark Phalan 
221159d09a2SMark Phalan static krb5_error_code pkinit_create_sequence_of_principal_identifiers
222159d09a2SMark Phalan 	(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx,
223159d09a2SMark Phalan 		pkinit_req_crypto_context req_cryptoctx,
224159d09a2SMark Phalan 		pkinit_identity_crypto_context id_cryptoctx,
225159d09a2SMark Phalan 		int type, krb5_data **out_data);
226159d09a2SMark Phalan 
227159d09a2SMark Phalan #ifndef WITHOUT_PKCS11
228159d09a2SMark Phalan static krb5_error_code pkinit_find_private_key
229159d09a2SMark Phalan 	(pkinit_identity_crypto_context, CK_ATTRIBUTE_TYPE usage,
230159d09a2SMark Phalan 		CK_OBJECT_HANDLE *objp);
231159d09a2SMark Phalan static krb5_error_code pkinit_login
232159d09a2SMark Phalan 	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
233159d09a2SMark Phalan 		CK_TOKEN_INFO *tip);
234159d09a2SMark Phalan static void * pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p);
235159d09a2SMark Phalan static CK_RV pkinit_C_UnloadModule(void *handle);
236159d09a2SMark Phalan #ifdef SILLYDECRYPT
237159d09a2SMark Phalan CK_RV pkinit_C_Decrypt
238159d09a2SMark Phalan 	(pkinit_identity_crypto_context id_cryptoctx,
239159d09a2SMark Phalan 		CK_BYTE_PTR pEncryptedData, CK_ULONG  ulEncryptedDataLen,
240159d09a2SMark Phalan 		CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
241159d09a2SMark Phalan #endif
242159d09a2SMark Phalan 
243159d09a2SMark Phalan static krb5_error_code pkinit_sign_data_pkcs11
244159d09a2SMark Phalan 	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
245159d09a2SMark Phalan 		unsigned char *data, unsigned int data_len,
246159d09a2SMark Phalan 		unsigned char **sig, unsigned int *sig_len);
247159d09a2SMark Phalan static krb5_error_code pkinit_decode_data_pkcs11
248159d09a2SMark Phalan 	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
249159d09a2SMark Phalan 		unsigned char *data, unsigned int data_len,
250159d09a2SMark Phalan 		unsigned char **decoded_data, unsigned int *decoded_data_len);
251159d09a2SMark Phalan #endif	/* WITHOUT_PKCS11 */
252159d09a2SMark Phalan 
253159d09a2SMark Phalan static krb5_error_code pkinit_sign_data_fs
254159d09a2SMark Phalan 	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
255159d09a2SMark Phalan 		unsigned char *data, unsigned int data_len,
256159d09a2SMark Phalan 		unsigned char **sig, unsigned int *sig_len);
257159d09a2SMark Phalan static krb5_error_code pkinit_decode_data_fs
258159d09a2SMark Phalan 	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
259159d09a2SMark Phalan 		unsigned char *data, unsigned int data_len,
260159d09a2SMark Phalan 		unsigned char **decoded_data, unsigned int *decoded_data_len);
261159d09a2SMark Phalan 
262159d09a2SMark Phalan static krb5_error_code der_decode_data
263159d09a2SMark Phalan 	(unsigned char *, long, unsigned char **, long *);
264159d09a2SMark Phalan 
265159d09a2SMark Phalan static krb5_error_code
266159d09a2SMark Phalan create_krb5_invalidCertificates(krb5_context context,
267159d09a2SMark Phalan 				pkinit_plg_crypto_context plg_cryptoctx,
268159d09a2SMark Phalan 				pkinit_req_crypto_context req_cryptoctx,
269159d09a2SMark Phalan 				pkinit_identity_crypto_context id_cryptoctx,
270159d09a2SMark Phalan 				krb5_external_principal_identifier *** ids);
271159d09a2SMark Phalan 
272159d09a2SMark Phalan static krb5_error_code
273159d09a2SMark Phalan create_identifiers_from_stack(STACK_OF(X509) *sk,
274159d09a2SMark Phalan 			      krb5_external_principal_identifier *** ids);
275159d09a2SMark Phalan #ifdef LONGHORN_BETA_COMPAT
276159d09a2SMark Phalan static int
277159d09a2SMark Phalan wrap_signeddata(unsigned char *data, unsigned int data_len,
278159d09a2SMark Phalan 		unsigned char **out, unsigned int *out_len,
279159d09a2SMark Phalan 		int is_longhorn_server);
280159d09a2SMark Phalan #else
281159d09a2SMark Phalan static int
282159d09a2SMark Phalan wrap_signeddata(unsigned char *data, unsigned int data_len,
283159d09a2SMark Phalan 		unsigned char **out, unsigned int *out_len);
284159d09a2SMark Phalan #endif
285159d09a2SMark Phalan 
286159d09a2SMark Phalan /* This handy macro borrowed from crypto/x509v3/v3_purp.c */
287300fdee2SAndy Fiddaman 
288*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
289159d09a2SMark Phalan #define ku_reject(x, usage) \
290159d09a2SMark Phalan 	(((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
291300fdee2SAndy Fiddaman #else
292300fdee2SAndy Fiddaman #define ku_reject(x, usage) \
293300fdee2SAndy Fiddaman 	((X509_get_extension_flags(x) & EXFLAG_KUSAGE) && \
294300fdee2SAndy Fiddaman 	!(X509_get_key_usage(x) & (usage)))
295300fdee2SAndy Fiddaman #endif
296159d09a2SMark Phalan 
297159d09a2SMark Phalan static char *
298159d09a2SMark Phalan pkinit_pkcs11_code_to_text(int err);
299159d09a2SMark Phalan 
300159d09a2SMark Phalan #endif	/* _PKINIT_CRYPTO_OPENSSL_H */
301