Re: [PATCH v2 1/6] SP800-90A Deterministic Random Bit Generator
Am Donnerstag, 20. März 2014, 09:12:55 schrieb Clemens Ladisch: Hi Clemens, > Stephan Mueller wrote: > > This is a clean-room implementation of the DRBG defined in SP800-90A. > > Why? I guess it's for certification? As per SP800-131A, the ANSI X9.31 DRNG is sunset by the end of 2014 and not allowed to be used in FIPS 140-2 compliant environments. The kernel crypto API implements an ANSI X9.31 DRNG in crypto/ansi_cprng.c as the only DRNG that complies with FIPS 140-2 at this time. Without a replacement for this ANSI X9.31 DRNG, the kernel will not have an FIPS 140-2 approved DRNG any more starting from 2015. > > > +static bool drbg_fips_continuous_test(struct drbg_state *drbg, > > +unsigned char *buf) > > ... > > + ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg)); > > + ... > > + /* invert the memcmp result, because the test shall pass when the > > +* two compared values do not match */ > > + if (ret) > > + return true; > > + else > > + return false; > > This looks strange. The return value of memcmp() is not really > a boolean, and the code appears not to match the comment because the > numeric value of ret is not actually inverted. How about this: Correct, the comment does not match the code as I had invered the logic of drbg_fips_continuous_test as per Rafael's comment. Yet, I did not update the comment. > > ret = memcmp(...); > ... > /* the test shall pass when the compared values are not equal */ > return ret != 0; I will add that change. > > > Regards, > Clemens Thanks Stephan -- | Cui bono? | -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 1/6] SP800-90A Deterministic Random Bit Generator
Stephan Mueller wrote: > This is a clean-room implementation of the DRBG defined in SP800-90A. Why? I guess it's for certification? > +static bool drbg_fips_continuous_test(struct drbg_state *drbg, > + unsigned char *buf) > ... > + ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg)); > + ... > + /* invert the memcmp result, because the test shall pass when the > + * two compared values do not match */ > + if (ret) > + return true; > + else > + return false; This looks strange. The return value of memcmp() is not really a boolean, and the code appears not to match the comment because the numeric value of ret is not actually inverted. How about this: ret = memcmp(...); ... /* the test shall pass when the compared values are not equal */ return ret != 0; Regards, Clemens -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 1/6] SP800-90A Deterministic Random Bit Generator
Am Montag, 17. März 2014, 08:34:06 schrieb Stephan Mueller: > +static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, > + bool reseed) > +{ > + int ret = 0; > + unsigned char *entropy = NULL; > + size_t entropylen = 0; > + struct drbg_string data1; > + struct drbg_string *data2; > + > + /* 9.1 / 9.2 / 9.3.1 step 3 */ > + if (pers && pers->len > (drbg_max_addtl(drbg))) > + return -EINVAL; > + > + if (drbg->test_data) { > + data1.buf = drbg->test_data->testentropy->buf; > + data1.len = drbg->test_data->testentropy->len; > + data1.next = NULL; > + } else { > + /* Gather entropy equal to the security strength of the DRBG. > + * With a derivation function, a nonce is required in addition > + * to the entropy. A nonce must be at least 1/2 of the security > + * strength of the DRBG in size. Thus, entropy * nonce is 3/2 > + * of the strength. The consideration of a nonce is only > + * applicable during initial seeding. */ > + entropylen = (drbg_sec_strength(drbg->core->flags) / 8); drbg_sec_strength returns the strength in bytes, thus the division by 8 must be removed > + if (!entropylen) > + return -EFAULT; > + if (!reseed) > + /* make sure we round up strength/2 in > + * case it is not divisible by 2 */ > + entropylen = ((entropylen + 1) / 2) * 3; > + > + entropy = kzalloc(entropylen, GFP_KERNEL); > + if (!entropy) > + return -ENOMEM; > + get_random_bytes(entropy, entropylen); > + drbg_string_fill(&data1, entropy, entropylen); > + } > + > + /* concatenation of entropy with personalization str / addtl input) */ > + if (pers && 0 < pers->len) { > + data2 = pers; > + data2->next = NULL; > + data1.next = data2; > + } > + > + ret = drbg->d_ops->update(drbg, &data1, reseed); > + if (ret) > + goto out; > + > + drbg->seeded = true; > + /* 10.1.1.2 / 10.1.1.3 step 5 */ > + drbg->reseed_ctr = 1; > + > +out: > + if (entropy) > + kzfree(entropy); > + return ret; > +} > + [...] > +static unsigned int drbg_generate(struct drbg_state *drbg, > + unsigned char *buf, unsigned int buflen, > + struct drbg_string *addtl) > +{ > + unsigned int len = 0; > + struct drbg_state *shadow = NULL; > + > + if (0 == buflen || !buf) > + return 0; > + if (addtl && NULL == addtl->buf && 0 < addtl->len) > + return 0; > + > + if (drbg_make_shadow(drbg, &shadow)) > + return 0; > + /* 9.3.1 step 2 */ > + if (buflen > (drbg_max_request_bytes(shadow))) > + goto err; > + /* 9.3.1 step 3 is implicit with the chosen DRBG */ > + /* 9.3.1 step 4 */ > + if (addtl && addtl->len > (drbg_max_addtl(shadow))) > + goto err; > + /* 9.3.1 step 5 is implicit with the chosen DRBG */ > + /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a > + * bit convoluted here, we make it simpler */ > + if ((drbg_max_requests(shadow)) < shadow->reseed_ctr) > + shadow->seeded = false; > + > + /* allocate cipher handle */ > + if (shadow->d_ops->crypto_init && shadow->d_ops->crypto_init(shadow)) > + goto err; > + > + if (shadow->pr || !shadow->seeded) { > + /* 9.3.1 steps 7.1 through 7.3 */ > + if (drbg_seed(shadow, addtl, true)) > + goto err; > + /* 9.3.1 step 7.4 */ > + addtl = NULL; > + } > + /* 9.3.1 step 8 and 10 */ > + len = drbg->d_ops->generate(shadow, buf, buflen, addtl); This needs to be shadow->d_ops > + > + /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */ > + shadow->reseed_ctr++; > + > +err: > + if (shadow->d_ops->crypto_fini) > + shadow->d_ops->crypto_fini(shadow); > + drbg_restore_shadow(drbg, &shadow); > + return len; > +} Ciao Stephan -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/6] SP800-90A Deterministic Random Bit Generator
This is a clean-room implementation of the DRBG defined in SP800-90A. All three viable DRBGs defined in the standard are implemented: * HMAC: This is the leanest DRBG and compiled per default * Hash: The more complex DRBG can be enabled at compile time * CTR: The most complex DRBG can also be enabled at compile time The DRBG implementation offers the following: * All three DRBG types are implemented with a derivation function. * All DRBG types are available with and without prediction resistance. * All SHA types of SHA-1, SHA-256, SHA-384, SHA-512 are available for * the HMAC and Hash DRBGs. * All AES types of AES-128, AES-192 and AES-256 are available for the * CTR DRBG. * A self test is implemented with drbg_healthcheck(). * The FIPS 140-2 continuous self test is implemented. * Additional cipher primitives, such as Serpent or Twofish, can be * added to the DRBG without changing the implementation. The only * change necessary is to the DRBG definition given in the cores[] * array. Changes to v1: * Overhauling code structure for simpler code as suggested by Rafael Aquini: - each DRBG type exports only two crypto functions, - the individual DRBG implementations structure closely according to SP 800-90A, - using struct drbg_string to refer to buffers to avoid too many function parameters and prevent multiple data structure conversions - use inline more thoroughly - replace macros with small inline functions - remove unnecessary indirections - replace of large stack variables with a scratch buffer allocated at the beginning of DRBG operation -- see comments about scratchpad throughout the code * Revamping DRBG flags usage: flags are only intended to select the appropriate DRBG type and DRBG strength. Flags are not intended to be visible to external callers. * Adding comments throughout the code to refer to the appropriate steps documented in SP 800-90A. * Fix invocation of kernel crypto API hash * Fix coding style and apply scripts/checkpatch.pl * Change locking approach: only very small code sections are guarded by a lock. This implies that the entire DRBG operates on a shadow copy of the original DRBG state -- see comments for drbg_copy_drbg * Perform thorough testing: - Performing of a full scale CAVS test with CAVS interface available at http://www.chronox.de/drbg.html - Performing tests by obtaining data which is not a multiple of cipher block size and check it with the ent tool to ensure that the generation loop does not reuse stale buffers to avoid errors like CVE-2013-4345. Signed-off-by: Stephan Mueller --- create mode 100644 crypto/drbg.c diff --git a/crypto/drbg.c b/crypto/drbg.c new file mode 100644 index 000..808852b --- /dev/null +++ b/crypto/drbg.c @@ -0,0 +1,1790 @@ +/* + * DRBG: Deterministic Random Bits Generator + * Based on NIST Recommended DRBG from NIST SP800-90A with the following + * properties: + * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores + * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores + * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores + * * with and without prediction resistance + * + * Copyright Stephan Mueller , 2014 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *notice, and the entire permission notice in its entirety, + *including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + *notice, this list of conditions and the following disclaimer in the + *documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + *products derived from this software without specific prior + *written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU General Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRA