From 581c850aa7ac63086a489480efa4cc0bf8cfd510 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Thu, 21 Aug 2014 21:26:27 +0200 Subject: [PATCH v9 7/7] User interface to DRBG DRBG Usage ========== The SP 800-90A DRBG allows the user to specify a personalization string for initialization as well as an additional information string for each random number request. The following code fragments show how a caller uses the kernel crypto API to use the full functionality of the DRBG. Usage without any additional data --------------------------------- gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); Usage with personalization string during initialization ------------------------------------------------------- struct drbg_string pers; drbg_string_fill(&pers, "string", strlen("string")); // The reset completely re-initializes the DRBG with the provided // personalization string without changing the DRBG type ret = gcry_control(GCRYCTL_DRBG_REINIT, 0, &pers, NULL); gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); Usage with additional information string during random number request --------------------------------------------------------------------- struct drbg_string addtl; drbg_string_fill(&addtl, "string", strlen("string")); // The following call is a wrapper to gcry_randomize() and returns // the same error codes. gcry_randomize_drbg(outbuf, OUTLEN, GCRY_STRONG_RANDOM, &addtl); Usage with personalization and additional information strings ------------------------------------------------------------- Just mix both scenarios above. Switch the DRBG type to some other type --------------------------------------- // Switch to CTR DRBG AES-128 without prediction resistance ret = gcry_control(GCRYCTL_DRBG_REINIT, DRBG_NOPR_CTRAES128, NULL, NULL); gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); Signed-off-by: Stephan Mueller --- src/gcrypt.h.in | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 144 insertions(+), 13 deletions(-) Index: libgcrypt-1.6.1/src/gcrypt.h.in =================================================================== --- libgcrypt-1.6.1.orig/src/gcrypt.h.in 2014-01-29 10:49:05.000000000 +0100 +++ libgcrypt-1.6.1/src/gcrypt.h.in 2014-09-02 13:45:42.439648231 +0200 @@ -193,7 +193,7 @@ gcry_error_t gcry_err_make_from_errno (g /* Return an error value with the system error ERR. */ gcry_err_code_t gcry_error_from_errno (int err); - + /* NOTE: Since Libgcrypt 1.6 the thread callbacks are not anymore used. However we keep it to allow for some source code compatibility if used in the standard way. */ @@ -228,7 +228,7 @@ struct gcry_thread_cbs (GCRY_THREAD_OPTION_PTHREAD | (GCRY_THREAD_OPTION_VERSION << 8))} - + /* A generic context object as used by some functions. */ struct gcry_context; typedef struct gcry_context *gcry_ctx_t; @@ -254,7 +254,7 @@ typedef struct } gcry_buffer_t; - + /* Check that the library fulfills the version requirement. */ const char *gcry_check_version (const char *req_version); @@ -329,7 +329,8 @@ enum gcry_ctl_cmds GCRYCTL_SET_CCM_LENGTHS = 69, GCRYCTL_CLOSE_RANDOM_DEVICE = 70, GCRYCTL_INACTIVATE_FIPS_FLAG = 71, - GCRYCTL_REACTIVATE_FIPS_FLAG = 72 + GCRYCTL_REACTIVATE_FIPS_FLAG = 72, + GCRYCTL_DRBG_REINIT = 74, }; /* Perform various operations defined by CMD. */ @@ -477,7 +478,7 @@ gpg_error_t gcry_sexp_extract_param (gcr const char *list, ...) _GCRY_GCC_ATTR_SENTINEL(0); - + /******************************************* * * * Multi Precision Integer Functions * @@ -833,7 +834,7 @@ gcry_mpi_t _gcry_mpi_get_const (int no); #endif /* GCRYPT_NO_MPI_MACROS */ - + /************************************ * * * Symmetric Cipher Functions * @@ -1015,7 +1016,7 @@ size_t gcry_cipher_get_algo_blklen (int #define gcry_cipher_test_algo(a) \ gcry_cipher_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL ) - + /************************************ * * * Asymmetric Cipher Functions * @@ -1114,7 +1115,7 @@ gcry_sexp_t gcry_pk_get_param (int algo, gcry_error_t gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx); - + /************************************ * * @@ -1291,7 +1292,7 @@ void gcry_md_debug (gcry_md_hd_t hd, con #define gcry_md_get_asnoid(a,b,n) \ gcry_md_algo_info((a), GCRYCTL_GET_ASNOID, (b), (n)) - + /********************************************** * * @@ -1407,7 +1408,7 @@ int gcry_mac_map_name (const char *name) #define gcry_mac_test_algo(a) \ gcry_mac_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL ) - + /****************************** * * * Key Derivation Functions * @@ -1435,7 +1436,7 @@ gpg_error_t gcry_kdf_derive (const void - + /************************************ * * * Random Generating Functions * @@ -1504,7 +1505,7 @@ void gcry_create_nonce (void *buffer, si - + /*******************************/ /* */ /* Prime Number Functions */ @@ -1563,7 +1564,7 @@ void gcry_prime_release_factors (gcry_mp gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags); - + /************************************ * * * Miscellaneous Stuff * @@ -1668,6 +1669,136 @@ int gcry_is_secure (const void *a) _GCRY /* Return true if Libgcrypt is in FIPS mode. */ #define gcry_fips_mode_active() !!gcry_control (GCRYCTL_FIPS_MODE_P, 0) +/* DRBG test data */ +struct drbg_test_data { + struct drbg_string *testentropy; /* TEST PARAMETER: test entropy */ + int fail_seed_source:1; /* if set, the seed function will return an + * error */ +}; + +/* DRBG input data structure for DRBG generate with additional information + * string */ +struct drbg_gen { + unsigned char *outbuf; /* output buffer for random numbers */ + unsigned int outlen; /* size of output buffer */ + struct drbg_string *addtl; /* input buffer for + * additional information string */ + struct drbg_test_data *test_data; /* test data */ +}; + +/* + * Concatenation Helper and string operation helper + * + * SP800-90A requires the concatenation of different data. To avoid copying + * buffers around or allocate additional memory, the following data structure + * is used to point to the original memory with its size. In addition, it + * is used to build a linked list. The linked list defines the concatenation + * of individual buffers. The order of memory block referenced in that + * linked list determines the order of concatenation. + */ +/* DRBG string definition */ +struct drbg_string { + const unsigned char *buf; + size_t len; + struct drbg_string *next; +}; + +static inline void drbg_string_fill(struct drbg_string *string, + const unsigned char *buf, size_t len) +{ + string->buf = buf; + string->len = len; + string->next = NULL; +} + +/* this is a wrapper function for users of libgcrypt */ +static inline void gcry_randomize_drbg(void *outbuf, size_t outlen, + enum gcry_random_level level, + struct drbg_string *addtl) +{ + struct drbg_gen genbuf; + genbuf.outbuf = (unsigned char *)outbuf; + genbuf.outlen = outlen; + genbuf.addtl = addtl; + genbuf.test_data = NULL; + gcry_randomize(&genbuf, 0, level); +} + +/* this is a wrapper function for users of libgcrypt */ +static inline void gcry_randomize_drbg_test(void *outbuf, size_t outlen, + enum gcry_random_level level, + struct drbg_string *addtl, + struct drbg_test_data *test_data) +{ + struct drbg_gen genbuf; + genbuf.outbuf = (unsigned char *)outbuf; + genbuf.outlen = outlen; + genbuf.addtl = addtl; + genbuf.test_data = test_data; + gcry_randomize(&genbuf, 0, level); +} + + +/* + * DRBG flags bitmasks + * + * 31 (B) 28 19 (A) 0 + * +-+-+-+--------+---+-----------+-----+ + * |~|~|u|~~~~~~~~| 3 | 2 | 1 | + * +-+-+-+--------+- -+-----------+-----+ + * ctl flg| |drbg use selection flags + * + */ + +/* internal state control flags (B) */ +#define DRBG_PREDICTION_RESIST ((u_int32_t)1<<28) + +/* CTR type modifiers (A.1)*/ +#define DRBG_CTRAES ((u_int32_t)1<<0) +#define DRBG_CTRSERPENT ((u_int32_t)1<<1) +#define DRBG_CTRTWOFISH ((u_int32_t)1<<2) +#define DRBG_CTR_MASK (DRBG_CTRAES | DRBG_CTRSERPENT | DRBG_CTRTWOFISH) + +/* HASH type modifiers (A.2)*/ +#define DRBG_HASHSHA1 ((u_int32_t)1<<4) +#define DRBG_HASHSHA224 ((u_int32_t)1<<5) +#define DRBG_HASHSHA256 ((u_int32_t)1<<6) +#define DRBG_HASHSHA384 ((u_int32_t)1<<7) +#define DRBG_HASHSHA512 ((u_int32_t)1<<8) +#define DRBG_HASH_MASK (DRBG_HASHSHA1 | DRBG_HASHSHA224 | \ + DRBG_HASHSHA256 | DRBG_HASHSHA384 | \ + DRBG_HASHSHA512) +/* type modifiers (A.3)*/ +#define DRBG_HMAC ((u_int32_t)1<<12) +#define DRBG_SYM128 ((u_int32_t)1<<13) +#define DRBG_SYM192 ((u_int32_t)1<<14) +#define DRBG_SYM256 ((u_int32_t)1<<15) +#define DRBG_TYPE_MASK (DRBG_HMAC | DRBG_SYM128 | DRBG_SYM192 | \ + DRBG_SYM256) +#define DRBG_CIPHER_MASK (DRBG_CTR_MASK | DRBG_HASH_MASK | DRBG_TYPE_MASK) + +#define DRBG_PR_CTRAES128 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM128) +#define DRBG_PR_CTRAES192 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM192) +#define DRBG_PR_CTRAES256 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM256) +#define DRBG_NOPR_CTRAES128 (DRBG_CTRAES | DRBG_SYM128) +#define DRBG_NOPR_CTRAES192 (DRBG_CTRAES | DRBG_SYM192) +#define DRBG_NOPR_CTRAES256 (DRBG_CTRAES | DRBG_SYM256) +#define DRBG_PR_HASHSHA1 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA1) +#define DRBG_PR_HASHSHA256 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA256) +#define DRBG_PR_HASHSHA384 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA384) +#define DRBG_PR_HASHSHA512 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA512) +#define DRBG_NOPR_HASHSHA1 (DRBG_HASHSHA1) +#define DRBG_NOPR_HASHSHA256 (DRBG_HASHSHA256) +#define DRBG_NOPR_HASHSHA384 (DRBG_HASHSHA384) +#define DRBG_NOPR_HASHSHA512 (DRBG_HASHSHA512) +#define DRBG_PR_HMACSHA1 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA1 | DRBG_HMAC) +#define DRBG_PR_HMACSHA256 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA256|DRBG_HMAC) +#define DRBG_PR_HMACSHA384 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA384|DRBG_HMAC) +#define DRBG_PR_HMACSHA512 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA512|DRBG_HMAC) +#define DRBG_NOPR_HMACSHA1 (DRBG_HASHSHA1 | DRBG_HMAC) +#define DRBG_NOPR_HMACSHA256 (DRBG_HASHSHA256 | DRBG_HMAC) +#define DRBG_NOPR_HMACSHA384 (DRBG_HASHSHA384 | DRBG_HMAC) +#define DRBG_NOPR_HMACSHA512 (DRBG_HASHSHA512 | DRBG_HMAC) #if 0 /* (Keep Emacsens' auto-indent happy.) */ {