1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/crypto/krb/crypto_int.h - Master libk5crypto internal header */
3 /*
4  * Copyright (C) 2011 by the Massachusetts Institute of Technology.
5  * All rights reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 
27 /* This header is the entry point for libk5crypto sources, and also documents
28  * requirements for crypto modules and PRNG modules.  */
29 
30 #ifndef CRYPTO_INT_H
31 #define CRYPTO_INT_H
32 
33 #include <k5-int.h>
34 
35 /* Enc providers and hash providers specify well-known ciphers and hashes to be
36  * implemented by the crypto module. */
37 
38 struct krb5_enc_provider {
39     /* keybytes is the input size to make_key;
40        keylength is the output size */
41     size_t block_size, keybytes, keylength;
42 
43     krb5_error_code (*encrypt)(krb5_key key, const krb5_data *cipher_state,
44                                krb5_crypto_iov *data, size_t num_data);
45 
46     krb5_error_code (*decrypt)(krb5_key key, const krb5_data *cipher_state,
47                                krb5_crypto_iov *data, size_t num_data);
48 
49     /* May be NULL if the cipher is not used for a cbc-mac checksum. */
50     krb5_error_code (*cbc_mac)(krb5_key key, const krb5_crypto_iov *data,
51                                size_t num_data, const krb5_data *ivec,
52                                krb5_data *output);
53 
54     krb5_error_code (*init_state)(const krb5_keyblock *key,
55                                   krb5_keyusage keyusage,
56                                   krb5_data *out_state);
57     void (*free_state)(krb5_data *state);
58 
59     /* May be NULL if there is no key-derived data cached.  */
60     void (*key_cleanup)(krb5_key key);
61 };
62 
63 struct krb5_hash_provider {
64     char hash_name[8];
65     size_t hashsize, blocksize;
66 
67     krb5_error_code (*hash)(const krb5_crypto_iov *data, size_t num_data,
68                             krb5_data *output);
69 };
70 
71 /*** RFC 3961 enctypes table ***/
72 
73 #define MAX_ETYPE_ALIASES 2
74 
75 struct krb5_keytypes;
76 
77 typedef unsigned int (*crypto_length_func)(const struct krb5_keytypes *ktp,
78                                            krb5_cryptotype type);
79 
80 typedef krb5_error_code (*crypt_func)(const struct krb5_keytypes *ktp,
81                                       krb5_key key, krb5_keyusage keyusage,
82                                       const krb5_data *ivec,
83                                       krb5_crypto_iov *data, size_t num_data);
84 
85 typedef krb5_error_code (*str2key_func)(const struct krb5_keytypes *ktp,
86                                         const krb5_data *string,
87                                         const krb5_data *salt,
88                                         const krb5_data *parm,
89                                         krb5_keyblock *key);
90 
91 typedef krb5_error_code (*rand2key_func)(const krb5_data *randombits,
92                                          krb5_keyblock *key);
93 
94 typedef krb5_error_code (*prf_func)(const struct krb5_keytypes *ktp,
95                                     krb5_key key,
96                                     const krb5_data *in, krb5_data *out);
97 
98 struct krb5_keytypes {
99     krb5_enctype etype;
100     char *name;
101     char *aliases[MAX_ETYPE_ALIASES];
102     char *out_string;
103     const struct krb5_enc_provider *enc;
104     const struct krb5_hash_provider *hash;
105     size_t prf_length;
106     crypto_length_func crypto_length;
107     crypt_func encrypt;
108     crypt_func decrypt;
109     str2key_func str2key;
110     rand2key_func rand2key;
111     prf_func prf;
112     krb5_cksumtype required_ctype;
113     krb5_flags flags;
114     unsigned int ssf;
115 };
116 
117 /*
118  * "Weak" means the enctype is believed to be vulnerable to practical attacks,
119  * and will be disabled unless allow_weak_crypto is set to true.  "Deprecated"
120  * means the enctype has been deprecated by the IETF, and affects display and
121  * logging.
122  */
123 #define ETYPE_WEAK (1 << 0)
124 #define ETYPE_DEPRECATED (1 << 1)
125 
126 extern const struct krb5_keytypes krb5int_enctypes_list[];
127 extern const int krb5int_enctypes_length;
128 
129 /*** RFC 3961 checksum types table ***/
130 
131 struct krb5_cksumtypes;
132 
133 /*
134  * Compute a checksum over the header, data, padding, and sign-only fields of
135  * the iov array data (of size num_data).  The output buffer will already be
136  * allocated with ctp->compute_size bytes available; the handler just needs to
137  * fill in the contents.  If ctp->enc is not NULL, the handler can assume that
138  * key is a valid-length key of an enctype which uses that enc provider.
139  */
140 typedef krb5_error_code (*checksum_func)(const struct krb5_cksumtypes *ctp,
141                                          krb5_key key, krb5_keyusage usage,
142                                          const krb5_crypto_iov *data,
143                                          size_t num_data,
144                                          krb5_data *output);
145 
146 /*
147  * Verify a checksum over the header, data, padding, and sign-only fields of
148  * the iov array data (of size num_data), and store the boolean result in
149  * *valid.  The handler can assume that hash has length ctp->output_size.  If
150  * ctp->enc is not NULL, the handler can assume that key a valid-length key of
151  * an enctype which uses that enc provider.
152  */
153 typedef krb5_error_code (*verify_func)(const struct krb5_cksumtypes *ctp,
154                                        krb5_key key, krb5_keyusage usage,
155                                        const krb5_crypto_iov *data,
156                                        size_t num_data,
157                                        const krb5_data *input,
158                                        krb5_boolean *valid);
159 
160 struct krb5_cksumtypes {
161     krb5_cksumtype ctype;
162     char *name;
163     char *aliases[2];
164     char *out_string;
165     const struct krb5_enc_provider *enc;
166     const struct krb5_hash_provider *hash;
167     checksum_func checksum;
168     verify_func verify;         /* NULL means recompute checksum and compare */
169     unsigned int compute_size;  /* Allocation size for checksum computation */
170     unsigned int output_size;   /* Possibly truncated output size */
171     krb5_flags flags;
172 };
173 
174 #define CKSUM_UNKEYED          0x0001
175 #define CKSUM_NOT_COLL_PROOF   0x0002
176 
177 extern const struct krb5_cksumtypes krb5int_cksumtypes_list[];
178 extern const size_t krb5int_cksumtypes_length;
179 
180 /*** Prototypes for enctype table functions ***/
181 
182 /* Length */
183 unsigned int krb5int_raw_crypto_length(const struct krb5_keytypes *ktp,
184                                        krb5_cryptotype type);
185 unsigned int krb5int_arcfour_crypto_length(const struct krb5_keytypes *ktp,
186                                            krb5_cryptotype type);
187 unsigned int krb5int_dk_crypto_length(const struct krb5_keytypes *ktp,
188                                       krb5_cryptotype type);
189 unsigned int krb5int_aes_crypto_length(const struct krb5_keytypes *ktp,
190                                        krb5_cryptotype type);
191 unsigned int krb5int_camellia_crypto_length(const struct krb5_keytypes *ktp,
192                                             krb5_cryptotype type);
193 unsigned int krb5int_aes2_crypto_length(const struct krb5_keytypes *ktp,
194                                         krb5_cryptotype type);
195 
196 /* Encrypt */
197 krb5_error_code krb5int_raw_encrypt(const struct krb5_keytypes *ktp,
198                                     krb5_key key, krb5_keyusage usage,
199                                     const krb5_data *ivec,
200                                     krb5_crypto_iov *data, size_t num_data);
201 krb5_error_code krb5int_arcfour_encrypt(const struct krb5_keytypes *ktp,
202                                         krb5_key key, krb5_keyusage usage,
203                                         const krb5_data *ivec,
204                                         krb5_crypto_iov *data,
205                                         size_t num_data);
206 krb5_error_code krb5int_dk_encrypt(const struct krb5_keytypes *ktp,
207                                    krb5_key key, krb5_keyusage usage,
208                                    const krb5_data *ivec,
209                                    krb5_crypto_iov *data, size_t num_data);
210 krb5_error_code krb5int_dk_cmac_encrypt(const struct krb5_keytypes *ktp,
211                                         krb5_key key, krb5_keyusage usage,
212                                         const krb5_data *ivec,
213                                         krb5_crypto_iov *data,
214                                         size_t num_data);
215 krb5_error_code krb5int_etm_encrypt(const struct krb5_keytypes *ktp,
216                                     krb5_key key, krb5_keyusage usage,
217                                     const krb5_data *ivec,
218                                     krb5_crypto_iov *data, size_t num_data);
219 
220 /* Decrypt */
221 krb5_error_code krb5int_raw_decrypt(const struct krb5_keytypes *ktp,
222                                     krb5_key key, krb5_keyusage usage,
223                                     const krb5_data *ivec,
224                                     krb5_crypto_iov *data, size_t num_data);
225 krb5_error_code krb5int_arcfour_decrypt(const struct krb5_keytypes *ktp,
226                                         krb5_key key, krb5_keyusage usage,
227                                         const krb5_data *ivec,
228                                         krb5_crypto_iov *data,
229                                         size_t num_data);
230 krb5_error_code krb5int_dk_decrypt(const struct krb5_keytypes *ktp,
231                                    krb5_key key, krb5_keyusage usage,
232                                    const krb5_data *ivec,
233                                    krb5_crypto_iov *data, size_t num_data);
234 krb5_error_code krb5int_dk_cmac_decrypt(const struct krb5_keytypes *ktp,
235                                         krb5_key key, krb5_keyusage usage,
236                                         const krb5_data *ivec,
237                                         krb5_crypto_iov *data,
238                                         size_t num_data);
239 krb5_error_code krb5int_etm_decrypt(const struct krb5_keytypes *ktp,
240                                     krb5_key key, krb5_keyusage usage,
241                                     const krb5_data *ivec,
242                                     krb5_crypto_iov *data, size_t num_data);
243 
244 /* String to key */
245 krb5_error_code krb5int_des_string_to_key(const struct krb5_keytypes *ktp,
246                                           const krb5_data *string,
247                                           const krb5_data *salt,
248                                           const krb5_data *params,
249                                           krb5_keyblock *key);
250 krb5_error_code krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp,
251                                               const krb5_data *string,
252                                               const krb5_data *salt,
253                                               const krb5_data *params,
254                                               krb5_keyblock *key);
255 krb5_error_code krb5int_dk_string_to_key(const struct krb5_keytypes *enc,
256                                          const krb5_data *string,
257                                          const krb5_data *salt,
258                                          const krb5_data *params,
259                                          krb5_keyblock *key);
260 krb5_error_code krb5int_aes_string_to_key(const struct krb5_keytypes *enc,
261                                           const krb5_data *string,
262                                           const krb5_data *salt,
263                                           const krb5_data *params,
264                                           krb5_keyblock *key);
265 krb5_error_code krb5int_camellia_string_to_key(const struct krb5_keytypes *enc,
266                                                const krb5_data *string,
267                                                const krb5_data *salt,
268                                                const krb5_data *params,
269                                                krb5_keyblock *key);
270 krb5_error_code krb5int_aes2_string_to_key(const struct krb5_keytypes *enc,
271                                            const krb5_data *string,
272                                            const krb5_data *salt,
273                                            const krb5_data *params,
274                                            krb5_keyblock *key);
275 
276 /* Random to key */
277 krb5_error_code k5_rand2key_direct(const krb5_data *randombits,
278                                    krb5_keyblock *keyblock);
279 krb5_error_code k5_rand2key_des(const krb5_data *randombits,
280                                 krb5_keyblock *keyblock);
281 krb5_error_code k5_rand2key_des3(const krb5_data *randombits,
282                                  krb5_keyblock *keyblock);
283 
284 /* Pseudo-random function */
285 krb5_error_code krb5int_des_prf(const struct krb5_keytypes *ktp,
286                                 krb5_key key, const krb5_data *in,
287                                 krb5_data *out);
288 krb5_error_code krb5int_arcfour_prf(const struct krb5_keytypes *ktp,
289                                     krb5_key key, const krb5_data *in,
290                                     krb5_data *out);
291 krb5_error_code krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key,
292                                const krb5_data *in, krb5_data *out);
293 krb5_error_code krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp,
294                                     krb5_key key, const krb5_data *in,
295                                     krb5_data *out);
296 krb5_error_code krb5int_aes2_prf(const struct krb5_keytypes *ktp, krb5_key key,
297                                  const krb5_data *in, krb5_data *out);
298 
299 /*** Prototypes for cksumtype handler functions ***/
300 
301 krb5_error_code krb5int_unkeyed_checksum(const struct krb5_cksumtypes *ctp,
302                                          krb5_key key, krb5_keyusage usage,
303                                          const krb5_crypto_iov *data,
304                                          size_t num_data,
305                                          krb5_data *output);
306 krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp,
307                                          krb5_key key, krb5_keyusage usage,
308                                          const krb5_crypto_iov *data,
309                                          size_t num_data,
310                                          krb5_data *output);
311 krb5_error_code krb5int_dk_checksum(const struct krb5_cksumtypes *ctp,
312                                     krb5_key key, krb5_keyusage usage,
313                                     const krb5_crypto_iov *data,
314                                     size_t num_data, krb5_data *output);
315 krb5_error_code krb5int_dk_cmac_checksum(const struct krb5_cksumtypes *ctp,
316                                          krb5_key key, krb5_keyusage usage,
317                                          const krb5_crypto_iov *data,
318                                          size_t num_data, krb5_data *output);
319 krb5_error_code krb5int_etm_checksum(const struct krb5_cksumtypes *ctp,
320                                      krb5_key key, krb5_keyusage usage,
321                                      const krb5_crypto_iov *data,
322                                      size_t num_data, krb5_data *output);
323 
324 /*** Key derivation functions ***/
325 
326 enum deriv_alg {
327     DERIVE_RFC3961,             /* RFC 3961 section 5.1 */
328     DERIVE_SP800_108_CMAC,      /* NIST SP 800-108 with CMAC as PRF */
329     DERIVE_SP800_108_HMAC       /* NIST SP 800-108 with HMAC as PRF */
330 };
331 
332 krb5_error_code krb5int_derive_keyblock(const struct krb5_enc_provider *enc,
333                                         const struct krb5_hash_provider *hash,
334                                         krb5_key inkey, krb5_keyblock *outkey,
335                                         const krb5_data *in_constant,
336                                         enum deriv_alg alg);
337 krb5_error_code krb5int_derive_key(const struct krb5_enc_provider *enc,
338                                    const struct krb5_hash_provider *hash,
339                                    krb5_key inkey, krb5_key *outkey,
340                                    const krb5_data *in_constant,
341                                    enum deriv_alg alg);
342 krb5_error_code krb5int_derive_random(const struct krb5_enc_provider *enc,
343                                       const struct krb5_hash_provider *hash,
344                                       krb5_key inkey, krb5_data *outrnd,
345                                       const krb5_data *in_constant,
346                                       enum deriv_alg alg);
347 krb5_error_code
348 k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
349                           krb5_key inkey, krb5_data *outrnd,
350                           const krb5_data *label, const krb5_data *context);
351 
352 /*** Miscellaneous prototypes ***/
353 
354 /* nfold algorithm from RFC 3961 */
355 void krb5int_nfold(unsigned int inbits, const unsigned char *in,
356                    unsigned int outbits, unsigned char *out);
357 
358 /* Compute a CMAC checksum over data. */
359 krb5_error_code krb5int_cmac_checksum(const struct krb5_enc_provider *enc,
360                                       krb5_key key,
361                                       const krb5_crypto_iov *data,
362                                       size_t num_data,
363                                       krb5_data *output);
364 
365 /* Translate an RFC 3961 key usage to a Microsoft RC4 usage. */
366 krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage);
367 
368 /* Ensure library initialization has occurred. */
369 int krb5int_crypto_init(void);
370 
371 /* DES default state initialization handler (used by module enc providers). */
372 krb5_error_code krb5int_des_init_state(const krb5_keyblock *key,
373                                        krb5_keyusage keyusage,
374                                        krb5_data *state_out);
375 
376 /* Default state cleanup handler (used by module enc providers). */
377 void krb5int_default_free_state(krb5_data *state);
378 
379 /*** Input/output vector processing declarations **/
380 
381 #define ENCRYPT_CONF_IOV(_iov)  ((_iov)->flags == KRB5_CRYPTO_TYPE_HEADER)
382 
383 #define ENCRYPT_DATA_IOV(_iov)  ((_iov)->flags == KRB5_CRYPTO_TYPE_DATA || \
384                                  (_iov)->flags == KRB5_CRYPTO_TYPE_PADDING)
385 
386 #define ENCRYPT_IOV(_iov)       (ENCRYPT_CONF_IOV(_iov) || ENCRYPT_DATA_IOV(_iov))
387 
388 #define SIGN_IOV(_iov)          (ENCRYPT_IOV(_iov) ||                   \
389                                  (_iov)->flags == KRB5_CRYPTO_TYPE_SIGN_ONLY )
390 
391 struct iov_cursor {
392     const krb5_crypto_iov *iov; /* iov array we are iterating over */
393     size_t iov_count;           /* size of iov array */
394     size_t block_size;          /* size of blocks we will be obtaining */
395     krb5_boolean signing;       /* should we process SIGN_ONLY blocks */
396     size_t in_iov;              /* read index into iov array */
397     size_t in_pos;              /* read index into iov contents */
398     size_t out_iov;             /* write index into iov array */
399     size_t out_pos;             /* write index into iov contents */
400 };
401 
402 krb5_crypto_iov *krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data,
403                                       krb5_cryptotype type);
404 
405 krb5_error_code krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp,
406                                              krb5_key key,
407                                              krb5_keyusage keyusage,
408                                              const krb5_data *ivec,
409                                              krb5_crypto_iov *data,
410                                              size_t num_data);
411 
412 unsigned int krb5int_c_padding_length(const struct krb5_keytypes *ktp,
413                                       size_t data_length);
414 
415 void k5_iov_cursor_init(struct iov_cursor *cursor, const krb5_crypto_iov *iov,
416                         size_t count, size_t block_size, krb5_boolean signing);
417 
418 krb5_boolean k5_iov_cursor_get(struct iov_cursor *cursor,
419                                unsigned char *block);
420 
421 void k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block);
422 
423 /*** Crypto module declarations ***/
424 
425 /* Modules must implement the k5_sha256() function prototyped in k5-int.h. */
426 
427 /* Modules must implement the following enc_providers and hash_providers: */
428 extern const struct krb5_enc_provider krb5int_enc_des3;
429 extern const struct krb5_enc_provider krb5int_enc_arcfour;
430 extern const struct krb5_enc_provider krb5int_enc_aes128;
431 extern const struct krb5_enc_provider krb5int_enc_aes256;
432 extern const struct krb5_enc_provider krb5int_enc_aes128_ctr;
433 extern const struct krb5_enc_provider krb5int_enc_aes256_ctr;
434 extern const struct krb5_enc_provider krb5int_enc_camellia128;
435 extern const struct krb5_enc_provider krb5int_enc_camellia256;
436 
437 extern const struct krb5_hash_provider krb5int_hash_md4;
438 extern const struct krb5_hash_provider krb5int_hash_md5;
439 extern const struct krb5_hash_provider krb5int_hash_sha1;
440 extern const struct krb5_hash_provider krb5int_hash_sha256;
441 extern const struct krb5_hash_provider krb5int_hash_sha384;
442 
443 /* Modules must implement the following functions. */
444 
445 /* Set the parity bits to the correct values in keybits. */
446 void k5_des_fixup_key_parity(unsigned char *keybits);
447 
448 /* Return true if keybits is a weak or semi-weak DES key. */
449 krb5_boolean k5_des_is_weak_key(unsigned char *keybits);
450 
451 /* Compute an HMAC using the provided hash function, key, and data, storing the
452  * result into output (caller-allocated). */
453 krb5_error_code krb5int_hmac(const struct krb5_hash_provider *hash,
454                              krb5_key key, const krb5_crypto_iov *data,
455                              size_t num_data, krb5_data *output);
456 
457 /* As above, using a keyblock as the key input. */
458 krb5_error_code krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
459                                       const krb5_keyblock *keyblock,
460                                       const krb5_crypto_iov *data,
461                                       size_t num_data, krb5_data *output);
462 
463 /*
464  * Compute the PBKDF2 (see RFC 2898) of password and salt, with the specified
465  * count, using HMAC with the specified hash as the pseudo-random function,
466  * storing the result into out (caller-allocated).
467  */
468 krb5_error_code krb5int_pbkdf2_hmac(const struct krb5_hash_provider *hash,
469                                     const krb5_data *out, unsigned long count,
470                                     const krb5_data *password,
471                                     const krb5_data *salt);
472 
473 /* The following are used by test programs and are just handler functions from
474  * the AES and Camellia enc providers. */
475 krb5_error_code krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec,
476                                     krb5_crypto_iov *data, size_t num_data);
477 krb5_error_code krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec,
478                                     krb5_crypto_iov *data, size_t num_data);
479 krb5_error_code krb5int_camellia_cbc_mac(krb5_key key,
480                                          const krb5_crypto_iov *data,
481                                          size_t num_data, const krb5_data *iv,
482                                          krb5_data *output);
483 
484 /* These can be used to safely set up and tear down module global state. */
485 int krb5int_crypto_impl_init(void);
486 void krb5int_crypto_impl_cleanup(void);
487 
488 /*
489  * Modules must provide a crypto_mod.h header at the top level.  To work with
490  * the default PRNG module (prng_fortuna.c), crypto_mod.h must #define or
491  * prototype the following symbols:
492  *
493  *   aes_encrypt_ctx - Stack-allocatable type for an AES-256 key schedule
494  *   k5_aes_encrypt_key256(key, ctxptr) -- initialize an AES-256 key schedule
495  *   k5_aes_encrypt(in, out, ctxptr) -- encrypt a block
496  *   SHA256_CTX - Stack-allocatable type for a SHA-256 hash state
497  *   k5_sha256_init(ctxptr) - Initialize a hash state
498  *   k5_sha256_update(ctxptr, data, size) -- Hash some data
499  *   k5_sha256_final(ctxptr, out) -- Finalize a state, writing hash into out
500  *
501  * These functions must never fail on valid inputs, and contexts must remain
502  * valid across forks.  If the module cannot meet those constraints, then it
503  * should provide its own PRNG module and the build system should ensure that
504  * it is used.
505  *
506  * The function symbols named above are also in the library export list (so
507  * they can be used by the t_fortuna.c test code), so even if the module
508  * defines them away or doesn't work with Fortuna, the module must provide
509  * stubs; see stubs.c in the openssl module for examples.
510  */
511 
512 #include <crypto_mod.h>
513 
514 /*** PRNG module declarations ***/
515 
516 /*
517  * PRNG modules must implement the following APIs from krb5.h:
518  *   krb5_c_random_add_entropy
519  *   krb5_c_random_make_octets
520  *   krb5_c_random_os_entropy
521  *
522  * PRNG modules should implement these functions.  They are called from the
523  * crypto library init and cleanup functions, and can be used to setup and tear
524  * down static state without thread safety concerns.
525  */
526 int k5_prng_init(void);
527 void k5_prng_cleanup(void);
528 
529 /* Used by PRNG modules to gather OS entropy.  Returns true on success. */
530 krb5_boolean k5_get_os_entropy(unsigned char *buf, size_t len, int strong);
531 
532 /*** Inline helper functions ***/
533 
534 /* Find an enctype by number in the enctypes table. */
535 static inline const struct krb5_keytypes *
find_enctype(krb5_enctype enctype)536 find_enctype(krb5_enctype enctype)
537 {
538     int i;
539 
540     for (i = 0; i < krb5int_enctypes_length; i++) {
541         if (krb5int_enctypes_list[i].etype == enctype)
542             break;
543     }
544 
545     if (i == krb5int_enctypes_length)
546         return NULL;
547     return &krb5int_enctypes_list[i];
548 }
549 
550 /* Find a checksum type by number in the cksumtypes table. */
551 static inline const struct krb5_cksumtypes *
find_cksumtype(krb5_cksumtype ctype)552 find_cksumtype(krb5_cksumtype ctype)
553 {
554     size_t i;
555 
556     for (i = 0; i < krb5int_cksumtypes_length; i++) {
557         if (krb5int_cksumtypes_list[i].ctype == ctype)
558             break;
559     }
560 
561     if (i == krb5int_cksumtypes_length)
562         return NULL;
563     return &krb5int_cksumtypes_list[i];
564 }
565 
566 /* Verify that a key is appropriate for a checksum type. */
567 static inline krb5_error_code
verify_key(const struct krb5_cksumtypes * ctp,krb5_key key)568 verify_key(const struct krb5_cksumtypes *ctp, krb5_key key)
569 {
570     const struct krb5_keytypes *ktp;
571 
572     ktp = key ? find_enctype(key->keyblock.enctype) : NULL;
573     if (ctp->enc != NULL && (!ktp || ktp->enc != ctp->enc))
574         return KRB5_BAD_ENCTYPE;
575     if (key && (!ktp || key->keyblock.length != ktp->enc->keylength))
576         return KRB5_BAD_KEYSIZE;
577     return 0;
578 }
579 
580 /* Encrypt one block of plaintext in place, for block ciphers. */
581 static inline krb5_error_code
encrypt_block(const struct krb5_enc_provider * enc,krb5_key key,krb5_data * block)582 encrypt_block(const struct krb5_enc_provider *enc, krb5_key key,
583               krb5_data *block)
584 {
585     krb5_crypto_iov iov;
586 
587     /* Verify that this is a block cipher and block is the right length. */
588     if (block->length != enc->block_size || enc->block_size == 1)
589         return EINVAL;
590     iov.flags = KRB5_CRYPTO_TYPE_DATA;
591     iov.data = *block;
592     if (enc->cbc_mac != NULL)   /* One-block cbc-mac with no ivec. */
593         return enc->cbc_mac(key, &iov, 1, NULL, block);
594     else                        /* Assume cbc-mode encrypt. */
595         return enc->encrypt(key, 0, &iov, 1);
596 }
597 
598 /* Return the total length of the to-be-signed or to-be-encrypted buffers in an
599  * iov chain. */
600 static inline size_t
iov_total_length(const krb5_crypto_iov * data,size_t num_data,krb5_boolean signing)601 iov_total_length(const krb5_crypto_iov *data, size_t num_data,
602                  krb5_boolean signing)
603 {
604     size_t i, total = 0;
605 
606     for (i = 0; i < num_data; i++) {
607         if (signing ? SIGN_IOV(&data[i]) : ENCRYPT_IOV(&data[i]))
608             total += data[i].data.length;
609     }
610     return total;
611 }
612 
613 /*
614  * Return the number of contiguous blocks available within the current input
615  * IOV of the cursor c, so that the caller can do in-place encryption.
616  * Do not call if c might be exhausted.
617  */
618 static inline size_t
iov_cursor_contig_blocks(struct iov_cursor * c)619 iov_cursor_contig_blocks(struct iov_cursor *c)
620 {
621     return (c->iov[c->in_iov].data.length - c->in_pos) / c->block_size;
622 }
623 
624 /* Return the current input pointer within the cursor c.  Do not call if c
625  * might be exhausted. */
626 static inline unsigned char *
iov_cursor_ptr(struct iov_cursor * c)627 iov_cursor_ptr(struct iov_cursor *c)
628 {
629     return (unsigned char *)&c->iov[c->in_iov].data.data[c->in_pos];
630 }
631 
632 /*
633  * Advance the input and output pointers of c by nblocks blocks.  nblocks must
634  * not be greater than the return value of iov_cursor_contig_blocks, and the
635  * input and output positions must be identical.
636  */
637 static inline void
iov_cursor_advance(struct iov_cursor * c,size_t nblocks)638 iov_cursor_advance(struct iov_cursor *c, size_t nblocks)
639 {
640     c->in_pos += nblocks * c->block_size;
641     c->out_pos += nblocks * c->block_size;
642 }
643 
644 #endif /* CRYPTO_INT_H */
645