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_DHKeyData;
115 ASN1_OBJECT *id_pkinit_rkeyData;
116 ASN1_OBJECT *id_pkinit_san;
117 ASN1_OBJECT *id_ms_san_upn;
118 ASN1_OBJECT *id_pkinit_KPClientAuth;
119 ASN1_OBJECT *id_pkinit_KPKdc;
120 ASN1_OBJECT *id_ms_kp_sc_logon;
121 ASN1_OBJECT *id_kp_serverAuth;
122 };
123
124 struct _pkinit_req_crypto_context {
125 X509 *received_cert;
126 DH *dh;
127 };
128
129 #define CERT_MAGIC 0x53534c43
130 struct _pkinit_cert_data {
131 unsigned int magic;
132 pkinit_plg_crypto_context plgctx;
133 pkinit_req_crypto_context reqctx;
134 pkinit_identity_crypto_context idctx;
135 pkinit_cred_info cred;
136 unsigned int index; /* Index of this cred in the creds[] array */
137 };
138
139 #define ITER_MAGIC 0x53534c49
140 struct _pkinit_cert_iter_data {
141 unsigned int magic;
142 pkinit_plg_crypto_context plgctx;
143 pkinit_req_crypto_context reqctx;
144 pkinit_identity_crypto_context idctx;
145 unsigned int index;
146 };
147
148 /* Solaris Kerberos */
149 static krb5_error_code openssl_init(void);
150
151 static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
152 static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
153
154 static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context );
155 static void pkinit_fini_dh_params(pkinit_plg_crypto_context );
156
157 static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx);
158 static void pkinit_fini_certs(pkinit_identity_crypto_context ctx);
159
160 static krb5_error_code pkinit_init_pkcs11(pkinit_identity_crypto_context ctx);
161 static void pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx);
162
163 static krb5_error_code pkinit_encode_dh_params
164 (BIGNUM *, BIGNUM *, BIGNUM *, unsigned char **, unsigned int *);
165 static DH *pkinit_decode_dh_params
166 (DH **, unsigned char **, unsigned int );
167 static int pkinit_check_dh_params
168 (BIGNUM * p1, BIGNUM * p2, BIGNUM * g1, BIGNUM * q1);
169
170 static krb5_error_code pkinit_sign_data
171 (krb5_context context, pkinit_identity_crypto_context cryptoctx,
172 unsigned char *data, unsigned int data_len,
173 unsigned char **sig, unsigned int *sig_len);
174
175 static krb5_error_code create_signature
176 (unsigned char **, unsigned int *, unsigned char *, unsigned int,
177 EVP_PKEY *pkey);
178
179 static krb5_error_code pkinit_decode_data
180 (krb5_context context, pkinit_identity_crypto_context cryptoctx,
181 unsigned char *data, unsigned int data_len,
182 unsigned char **decoded, unsigned int *decoded_len);
183
184 static krb5_error_code decode_data
185 (unsigned char **, unsigned int *, unsigned char *, unsigned int,
186 EVP_PKEY *pkey, X509 *cert);
187
188 #ifdef DEBUG_DH
189 static void print_dh(DH *, char *);
190 static void print_pubkey(BIGNUM *, char *);
191 #endif
192
193 static int prepare_enc_data
194 (unsigned char *indata, int indata_len, unsigned char **outdata,
195 int *outdata_len);
196
197 static int openssl_callback (int, X509_STORE_CTX *);
198 static int openssl_callback_ignore_crls (int, X509_STORE_CTX *);
199
200 static int pkcs7_decrypt
201 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
202 PKCS7 *p7, BIO *bio);
203
204 static BIO * pkcs7_dataDecode
205 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
206 PKCS7 *p7);
207
208 static ASN1_OBJECT * pkinit_pkcs7type2oid
209 (pkinit_plg_crypto_context plg_cryptoctx, int pkcs7_type);
210
211 static krb5_error_code pkinit_create_sequence_of_principal_identifiers
212 (krb5_context context, pkinit_plg_crypto_context plg_cryptoctx,
213 pkinit_req_crypto_context req_cryptoctx,
214 pkinit_identity_crypto_context id_cryptoctx,
215 int type, krb5_data **out_data);
216
217 #ifndef WITHOUT_PKCS11
218 static krb5_error_code pkinit_find_private_key
219 (pkinit_identity_crypto_context, CK_ATTRIBUTE_TYPE usage,
220 CK_OBJECT_HANDLE *objp);
221 static krb5_error_code pkinit_login
222 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
223 CK_TOKEN_INFO *tip);
224 static void * pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p);
225 static CK_RV pkinit_C_UnloadModule(void *handle);
226 #ifdef SILLYDECRYPT
227 CK_RV pkinit_C_Decrypt
228 (pkinit_identity_crypto_context id_cryptoctx,
229 CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
230 CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
231 #endif
232
233 static krb5_error_code pkinit_sign_data_pkcs11
234 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
235 unsigned char *data, unsigned int data_len,
236 unsigned char **sig, unsigned int *sig_len);
237 static krb5_error_code pkinit_decode_data_pkcs11
238 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
239 unsigned char *data, unsigned int data_len,
240 unsigned char **decoded_data, unsigned int *decoded_data_len);
241 #endif /* WITHOUT_PKCS11 */
242
243 static krb5_error_code pkinit_sign_data_fs
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_fs
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
252 static krb5_error_code der_decode_data
253 (unsigned char *, long, unsigned char **, long *);
254
255 static krb5_error_code
256 create_krb5_invalidCertificates(krb5_context context,
257 pkinit_plg_crypto_context plg_cryptoctx,
258 pkinit_req_crypto_context req_cryptoctx,
259 pkinit_identity_crypto_context id_cryptoctx,
260 krb5_external_principal_identifier *** ids);
261
262 static krb5_error_code
263 create_identifiers_from_stack(STACK_OF(X509) *sk,
264 krb5_external_principal_identifier *** ids);
265 #ifdef LONGHORN_BETA_COMPAT
266 static int
267 wrap_signeddata(unsigned char *data, unsigned int data_len,
268 unsigned char **out, unsigned int *out_len,
269 int is_longhorn_server);
270 #else
271 static int
272 wrap_signeddata(unsigned char *data, unsigned int data_len,
273 unsigned char **out, unsigned int *out_len);
274 #endif
275
276 /* This handy macro borrowed from crypto/x509v3/v3_purp.c */
277 #define ku_reject(x, usage) \
278 (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
279
280 static char *
281 pkinit_pkcs11_code_to_text(int err);
282
283 #endif /* _PKINIT_CRYPTO_OPENSSL_H */