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 #ifndef _PKINIT_H
32 #define _PKINIT_H
33
34 #include <k5-platform.h>
35 #include <krb5/krb5.h>
36 #include <krb5/preauth_plugin.h>
37 #include <k5-int-pkinit.h>
38 #include <profile.h>
39 #include "pkinit_accessor.h"
40 #include "pkinit_trace.h"
41
42 #ifndef WITHOUT_PKCS11
43 #include "pkcs11.h"
44
45 #define PK_SIGLEN_GUESS 1000
46 #define PK_NOSLOT 999999
47 #endif
48
49 #define DH_PROTOCOL 1
50 #define RSA_PROTOCOL 2
51
52 #define TD_TRUSTED_CERTIFIERS 104
53 #define TD_INVALID_CERTIFICATES 105
54 #define TD_DH_PARAMETERS 109
55
56 #define PKINIT_CTX_MAGIC 0x05551212
57 #define PKINIT_REQ_CTX_MAGIC 0xdeadbeef
58 #define PKINIT_DEFERRED_ID_MAGIC 0x3ca20d21
59
60 #define PKINIT_DEFAULT_DH_MIN_BITS 2048
61 #define PKINIT_DH_MIN_CONFIG_BITS 1024
62 /* Rough finite-field bit strength equivalents for the elliptic curve groups */
63 #define PKINIT_DH_P256_BITS 3072
64 #define PKINIT_DH_P384_BITS 7680
65 #define PKINIT_DH_P521_BITS 15360
66
67 #define KRB5_CONF_KDCDEFAULTS "kdcdefaults"
68 #define KRB5_CONF_LIBDEFAULTS "libdefaults"
69 #define KRB5_CONF_REALMS "realms"
70 #define KRB5_CONF_PKINIT_ALLOW_UPN "pkinit_allow_upn"
71 #define KRB5_CONF_PKINIT_ANCHORS "pkinit_anchors"
72 #define KRB5_CONF_PKINIT_INDICATOR "pkinit_indicator"
73 #define KRB5_CONF_PKINIT_CERT_MATCH "pkinit_cert_match"
74 #define KRB5_CONF_PKINIT_DH_MIN_BITS "pkinit_dh_min_bits"
75 #define KRB5_CONF_PKINIT_EKU_CHECKING "pkinit_eku_checking"
76 #define KRB5_CONF_PKINIT_IDENTITIES "pkinit_identities"
77 #define KRB5_CONF_PKINIT_IDENTITY "pkinit_identity"
78 #define KRB5_CONF_PKINIT_KDC_HOSTNAME "pkinit_kdc_hostname"
79 /* pkinit_kdc_ocsp has been removed */
80 #define KRB5_CONF_PKINIT_KDC_OCSP "pkinit_kdc_ocsp"
81 #define KRB5_CONF_PKINIT_POOL "pkinit_pool"
82 #define KRB5_CONF_PKINIT_REQUIRE_CRL_CHECKING "pkinit_require_crl_checking"
83 #define KRB5_CONF_PKINIT_REQUIRE_FRESHNESS "pkinit_require_freshness"
84 #define KRB5_CONF_PKINIT_REVOKE "pkinit_revoke"
85
86 /* Make pkiDebug(fmt,...) print, or not. */
87 #ifdef DEBUG
88 #define pkiDebug printf
89 #else
90 /* Still evaluates for side effects. */
pkiDebug(const char * fmt,...)91 static inline void pkiDebug (const char *fmt, ...) { }
92 /* This is better if the compiler doesn't inline variadic functions
93 well, but gcc will warn about "left-hand operand of comma
94 expression has no effect". Still evaluates for side effects. */
95 /* #define pkiDebug (void) */
96 #endif
97
98 /* Solaris compiler doesn't grok __FUNCTION__
99 * hack for now. Fix all the uses eventually. */
100 #ifndef _WIN32
101 #define __FUNCTION__ __func__
102 #endif
103
104 /* Macros to deal with converting between various data types... */
105 #define PADATA_TO_KRB5DATA(pad, k5d) \
106 (k5d)->length = (pad)->length; (k5d)->data = (char *)(pad)->contents;
107 #define OCTETDATA_TO_KRB5DATA(octd, k5d) \
108 (k5d)->length = (octd)->length; (k5d)->data = (char *)(octd)->data;
109
110 /*
111 * notes about crypto contexts:
112 *
113 * the basic idea is that there are crypto contexts that live at
114 * both the plugin level and request level. the identity context (that
115 * keeps info about your own certs and such) is separate because
116 * it is needed at different levels for the kdc and and the client.
117 * (the kdc's identity is at the plugin level, the client's identity
118 * information could change per-request.)
119 * the identity context is meant to have the entity's cert,
120 * a list of trusted and intermediate cas, a list of crls, and any
121 * pkcs11 information. the req context is meant to have the
122 * received certificate and the DH related information. the plugin
123 * context is meant to have global crypto information, i.e., OIDs
124 * and constant DH parameter information.
125 */
126
127 /*
128 * plugin crypto context should keep plugin common information,
129 * eg., OIDs, known DHparams
130 */
131 typedef struct _pkinit_plg_crypto_context *pkinit_plg_crypto_context;
132
133 /*
134 * request crypto context should keep reqyest common information,
135 * eg., received credentials, DH parameters of this request
136 */
137 typedef struct _pkinit_req_crypto_context *pkinit_req_crypto_context;
138
139 /*
140 * identity context should keep information about credentials
141 * for the request, eg., my credentials, trusted ca certs,
142 * intermediate ca certs, crls, pkcs11 info
143 */
144 typedef struct _pkinit_identity_crypto_context *pkinit_identity_crypto_context;
145
146 /*
147 * this structure keeps information about the config options
148 */
149 typedef struct _pkinit_plg_opts {
150 int require_eku; /* require EKU checking (default is true) */
151 int accept_secondary_eku;/* accept secondary EKU (default is false) */
152 int allow_upn; /* allow UPN-SAN instead of pkinit-SAN */
153 int require_crl_checking; /* require CRL for a CA (default is false) */
154 int require_freshness; /* require freshness token (default is false) */
155 int disable_freshness; /* disable freshness token on client for testing */
156 int dh_min_bits; /* minimum DH modulus size allowed */
157 } pkinit_plg_opts;
158
159 /*
160 * this structure keeps options used for a given request
161 */
162 typedef struct _pkinit_req_opts {
163 int require_eku;
164 int accept_secondary_eku;
165 int allow_upn;
166 int require_crl_checking;
167 int dh_size; /* initial request DH modulus size (default=1024) */
168 int require_hostname_match;
169 int disable_freshness;
170 } pkinit_req_opts;
171
172 /*
173 * information about identity from config file or command line
174 */
175
176 typedef struct _pkinit_identity_opts {
177 char *identity;
178 char **identity_alt;
179 char **anchors;
180 char **intermediates;
181 char **crls;
182 int idtype;
183 char *cert_filename;
184 char *key_filename;
185 #ifndef WITHOUT_PKCS11
186 char *p11_module_name;
187 CK_SLOT_ID slotid;
188 char *token_label;
189 char *cert_id_string;
190 char *cert_label;
191 #endif
192 } pkinit_identity_opts;
193
194
195 /*
196 * Client's plugin context
197 */
198 struct _pkinit_context {
199 int magic;
200 pkinit_plg_crypto_context cryptoctx;
201 pkinit_plg_opts *opts;
202 pkinit_identity_opts *idopts;
203 };
204 typedef struct _pkinit_context *pkinit_context;
205
206 /*
207 * Client's per-request context
208 */
209 struct _pkinit_req_context {
210 unsigned int magic;
211 pkinit_req_crypto_context cryptoctx;
212 pkinit_req_opts *opts;
213 pkinit_identity_crypto_context idctx;
214 pkinit_identity_opts *idopts;
215 int do_identity_matching;
216 krb5_preauthtype pa_type;
217 int rfc6112_kdc;
218 int identity_initialized;
219 int identity_prompted;
220 krb5_error_code identity_prompt_retval;
221 krb5_data *freshness_token;
222 };
223 typedef struct _pkinit_req_context *pkinit_req_context;
224
225 /*
226 * KDC's (per-realm) plugin context
227 */
228 struct _pkinit_kdc_context {
229 int magic;
230 pkinit_plg_crypto_context cryptoctx;
231 pkinit_plg_opts *opts;
232 pkinit_identity_crypto_context idctx;
233 pkinit_identity_opts *idopts;
234 char *realmname;
235 unsigned int realmname_len;
236 char **auth_indicators;
237 };
238 typedef struct _pkinit_kdc_context *pkinit_kdc_context;
239
240 /*
241 * KDC's per-request context
242 */
243 struct _pkinit_kdc_req_context {
244 int magic;
245 pkinit_req_crypto_context cryptoctx;
246 krb5_auth_pack *rcv_auth_pack;
247 krb5_preauthtype pa_type;
248 };
249 typedef struct _pkinit_kdc_req_context *pkinit_kdc_req_context;
250
251 /*
252 * Functions in pkinit_lib.c
253 */
254
255 krb5_error_code pkinit_init_req_opts(pkinit_req_opts **);
256 void pkinit_fini_req_opts(pkinit_req_opts *);
257
258 krb5_error_code pkinit_init_plg_opts(pkinit_plg_opts **);
259 void pkinit_fini_plg_opts(pkinit_plg_opts *);
260
261 krb5_error_code pkinit_init_identity_opts(pkinit_identity_opts **idopts);
262 void pkinit_fini_identity_opts(pkinit_identity_opts *idopts);
263 krb5_error_code pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
264 pkinit_identity_opts **dest_opts);
265
266 /*
267 * Functions in pkinit_identity.c
268 */
269 char * idtype2string(int idtype);
270 char * catype2string(int catype);
271
272 krb5_error_code pkinit_identity_initialize
273 (krb5_context context, /* IN */
274 pkinit_plg_crypto_context plg_cryptoctx, /* IN */
275 pkinit_req_crypto_context req_cryptoctx, /* IN */
276 pkinit_identity_opts *idopts, /* IN */
277 pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */
278 krb5_clpreauth_callbacks cb, /* IN/OUT */
279 krb5_clpreauth_rock rock, /* IN/OUT */
280 krb5_principal princ); /* IN (optional) */
281
282 krb5_error_code pkinit_identity_prompt
283 (krb5_context context, /* IN */
284 pkinit_plg_crypto_context plg_cryptoctx, /* IN */
285 pkinit_req_crypto_context req_cryptoctx, /* IN */
286 pkinit_identity_opts *idopts, /* IN */
287 pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */
288 krb5_clpreauth_callbacks cb, /* IN/OUT */
289 krb5_clpreauth_rock rock, /* IN/OUT */
290 int do_matching, /* IN */
291 krb5_principal princ); /* IN (optional) */
292
293 krb5_error_code pkinit_cert_matching
294 (krb5_context context,
295 pkinit_plg_crypto_context plg_cryptoctx,
296 pkinit_req_crypto_context req_cryptoctx,
297 pkinit_identity_crypto_context id_cryptoctx,
298 krb5_principal princ);
299
300 krb5_error_code pkinit_client_cert_match
301 (krb5_context context,
302 pkinit_plg_crypto_context plgctx,
303 pkinit_req_crypto_context reqctx,
304 const char *match_rule,
305 krb5_boolean *matched);
306
307 /*
308 * Client's list of identities for which it needs PINs or passwords
309 */
310 struct _pkinit_deferred_id {
311 int magic;
312 char *identity;
313 unsigned long ck_flags;
314 char *password;
315 };
316 typedef struct _pkinit_deferred_id *pkinit_deferred_id;
317
318 krb5_error_code pkinit_set_deferred_id
319 (pkinit_deferred_id **identities, const char *identity,
320 unsigned long ck_flags, const char *password);
321 const char * pkinit_find_deferred_id
322 (pkinit_deferred_id *identities, const char *identity);
323 unsigned long pkinit_get_deferred_id_flags
324 (pkinit_deferred_id *identities, const char *identity);
325 void pkinit_free_deferred_ids(pkinit_deferred_id *identities);
326
327 /*
328 * initialization and free functions
329 */
330 void init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
331 void init_krb5_reply_key_pack(krb5_reply_key_pack **in);
332
333 void init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
334
335 void free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
336 void free_krb5_reply_key_pack(krb5_reply_key_pack **in);
337 void free_krb5_auth_pack(krb5_auth_pack **in);
338 void free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
339 void free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in);
340 void free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in);
341 void free_krb5_algorithm_identifier(krb5_algorithm_identifier *in);
342 void free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in);
343 void free_pachecksum2(krb5_context context, krb5_pachecksum2 **in);
344 krb5_error_code pkinit_copy_krb5_data(krb5_data *dst, const krb5_data *src);
345
346
347 /*
348 * Functions in pkinit_profile.c
349 */
350 krb5_error_code pkinit_kdcdefault_strings
351 (krb5_context context, const char *realmname, const char *option,
352 char ***ret_value);
353 krb5_error_code pkinit_kdcdefault_string
354 (krb5_context context, const char *realmname, const char *option,
355 char **ret_value);
356 krb5_error_code pkinit_kdcdefault_boolean
357 (krb5_context context, const char *realmname, const char *option,
358 int default_value, int *ret_value);
359 krb5_error_code pkinit_kdcdefault_integer
360 (krb5_context context, const char *realmname, const char *option,
361 int default_value, int *ret_value);
362
363
364 krb5_error_code pkinit_libdefault_strings
365 (krb5_context context, const krb5_data *realm,
366 const char *option, char ***ret_value);
367 krb5_error_code pkinit_libdefault_string
368 (krb5_context context, const krb5_data *realm,
369 const char *option, char **ret_value);
370 krb5_error_code pkinit_libdefault_boolean
371 (krb5_context context, const krb5_data *realm, const char *option,
372 int default_value, int *ret_value);
373 krb5_error_code pkinit_libdefault_integer
374 (krb5_context context, const krb5_data *realm, const char *option,
375 int default_value, int *ret_value);
376
377 /*
378 * debugging functions
379 */
380 void print_buffer(const unsigned char *, unsigned int);
381 void print_buffer_bin(unsigned char *, unsigned int, char *);
382
383 /*
384 * Now get crypto function declarations
385 */
386 #include "pkinit_crypto.h"
387
388 #endif /* _PKINIT_H */
389