232 lines
7.8 KiB
C
232 lines
7.8 KiB
C
/* Copyright (c) (2015,2016,2017,2019) Apple Inc. All rights reserved.
|
||
*
|
||
* corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which
|
||
* is contained in the License.txt file distributed with corecrypto) and only to
|
||
* people who accept that license. IMPORTANT: Any license rights granted to you by
|
||
* Apple Inc. (if any) are limited to internal use within your organization only on
|
||
* devices and computers you own or control, for the sole purpose of verifying the
|
||
* security characteristics and correct functioning of the Apple Software. You may
|
||
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
|
||
*/
|
||
|
||
#include <corecrypto/ccdrbg.h>
|
||
#include "cc_debug.h"
|
||
#include <corecrypto/ccaes.h>
|
||
#include <corecrypto/ccsha2.h>
|
||
#include <corecrypto/ccdrbg.h>
|
||
#include "../corecrypto_test/include/testbyteBuffer.h"
|
||
#include <stdlib.h>
|
||
#include <limits.h>
|
||
#include "testmore.h"
|
||
#include "ccdrbg_test.h"
|
||
#include <corecrypto/cc_macros.h>
|
||
|
||
|
||
//very boring piece of code
|
||
typedef void (*ccdrbg_factory_t)(struct ccdrbg_info *, void *);
|
||
#define ok2(cond, s) (ok((cond), (s))?0:-1)
|
||
static const char *s32 = "01234567890123456789012345678901";
|
||
static const int WHATEVER=5;
|
||
|
||
static int drbg_init_limits_test( ccdrbg_factory_t ccdrbg_factory, void *custom)
|
||
{
|
||
struct ccdrbg_info drbg;
|
||
int rc, rc2;
|
||
struct ccdrbg_state *state;
|
||
char *entropy=" ";
|
||
char *nonce=" ";
|
||
char *ps=" ";
|
||
|
||
//too much entropy
|
||
ccdrbg_factory(&drbg, custom);
|
||
char b[drbg.size]; state = (struct ccdrbg_state *) b;
|
||
rc = ccdrbg_init(&drbg, state, CCDRBG_MAX_ENTROPY_SIZE+1, entropy, WHATEVER, nonce, WHATEVER, ps);
|
||
rc2 = ok2(rc!=0, "drbg init: max entropy length test failed");
|
||
|
||
//too little entropy
|
||
ccdrbg_factory(&drbg, custom);
|
||
rc = ccdrbg_init(&drbg, state, 0, entropy, WHATEVER, nonce, WHATEVER, ps);
|
||
rc2|=ok2(rc!=0, "drbg init: min entropy length test failed");
|
||
|
||
//no test for nonce as it ias not checked.
|
||
|
||
//too much PS
|
||
ccdrbg_factory(&drbg, custom);
|
||
rc = ccdrbg_init(&drbg, state, 32, s32, WHATEVER, nonce, CCDRBG_MAX_PSINPUT_SIZE+1, ps);
|
||
rc2|=ok2(rc!=0, "drbg init: max personalization string length test failed");
|
||
|
||
//NULL PS
|
||
ccdrbg_factory(&drbg, custom);
|
||
rc = ccdrbg_init(&drbg, state, 32, s32, WHATEVER, s32, 0, NULL);
|
||
rc2|=ok2(rc==0, "drbg init: NULL personalization string test failed");
|
||
|
||
return rc2;
|
||
}
|
||
|
||
static int drbg_reseed_limits_test( ccdrbg_factory_t ccdrbg_factory, void *custom)
|
||
{
|
||
struct ccdrbg_info drbg;
|
||
int rc, rc2;
|
||
struct ccdrbg_state *state;
|
||
|
||
//init
|
||
ccdrbg_factory(&drbg, custom);
|
||
char b[drbg.size]; state = (struct ccdrbg_state *) b;
|
||
rc = ccdrbg_init(&drbg, state, 32, s32, WHATEVER, s32, WHATEVER, s32);
|
||
rc2 = ok2(rc==0, "drbg init failed");
|
||
|
||
//too much entropy
|
||
rc = drbg.reseed(state, CCDRBG_MAX_ENTROPY_SIZE+1, s32, WHATEVER, s32);
|
||
rc2 |= ok2(rc!=0, "drbg reseed: max entropy length test failed");
|
||
|
||
//too little entropy
|
||
rc = drbg.reseed(state, 2, s32, WHATEVER, s32);
|
||
rc2|=ok2(rc!=0, "drbg reseed: min entropy length test failed");
|
||
|
||
|
||
//too much additional input
|
||
rc = drbg.reseed(state, 32, s32, CCDRBG_MAX_ADDITIONALINPUT_SIZE+1, s32);
|
||
rc2|=ok2(rc!=0, "drbg reseed: max personalization string length test failed");
|
||
|
||
//reseed with NULL additional input
|
||
rc = drbg.reseed(state, 32, s32, 0, NULL);
|
||
rc2|=ok2(rc==0, "drbg reseed: NULL personalization string test failed");
|
||
|
||
return rc2;
|
||
}
|
||
|
||
static int drbg_generate_limits_test( ccdrbg_factory_t ccdrbg_factory, void *custom)
|
||
{
|
||
struct ccdrbg_info drbg;
|
||
int rc, rc2;
|
||
struct ccdrbg_state *state;
|
||
char out[1024];
|
||
uint64_t v1,v2;
|
||
uint64_t v12[2];
|
||
|
||
ccdrbg_factory(&drbg, custom);
|
||
char b[drbg.size]; state = (struct ccdrbg_state *) b;
|
||
|
||
// one chunk 8 bytes
|
||
rc = ccdrbg_init(&drbg, state, 32, s32, WHATEVER, s32, WHATEVER, s32);
|
||
rc2 = ok2(rc==0, "drbg init failed");
|
||
rc = ccdrbg_generate(&drbg,state, sizeof(v12), v12, WHATEVER, s32);
|
||
rc2|=ok2(rc==0, "drbg generate: input 8 failed");
|
||
|
||
// Same as 2x 4bytes must not be the same as single shot 8bytes.
|
||
rc = ccdrbg_init(&drbg, state, 32, s32, WHATEVER, s32, WHATEVER, s32);
|
||
rc2 |= ok2(rc==0, "drbg init failed");
|
||
rc = ccdrbg_generate(&drbg,state, sizeof(v1), &v1, WHATEVER, s32);
|
||
rc2|=ok2(rc==0, "drbg generate: input 4 failed");
|
||
rc = ccdrbg_generate(&drbg,state, sizeof(v2), &v2, WHATEVER, s32);
|
||
rc2|=ok2(rc==0, "drbg generate: input 4 failed");
|
||
rc2|=ok2((v1==v12[0]) && (v2!=v12[1]), "drbg generate must differ");
|
||
|
||
// Generate with 0 byte is supported, it does not return any bytes
|
||
// but it updates the internal state
|
||
rc = ccdrbg_init(&drbg, state, 32, s32, WHATEVER, s32, WHATEVER, s32);
|
||
rc2 |= ok2(rc==0, "drbg init failed");
|
||
rc = ccdrbg_generate(&drbg,state, 0, NULL, WHATEVER, s32);
|
||
rc2|=ok2(rc==0, "drbg generate: input 0 failed");
|
||
rc = ccdrbg_generate(&drbg,state, sizeof(v12), out, WHATEVER, s32);
|
||
rc2|=ok2(rc==0, "drbg generate: input 4 failed");
|
||
rc2|=ok2(memcmp(v12,out,sizeof(v12))!=0, "drbg generate must differ");
|
||
|
||
// Output too big, check for error
|
||
rc = ccdrbg_generate(&drbg,state, CCDRBG_MAX_REQUEST_SIZE+1, out, WHATEVER, s32);
|
||
rc2|=ok2(rc!=0, "drbg generate: maximum input len failed");
|
||
|
||
// Personalization string is too big, check for error
|
||
rc = ccdrbg_generate(&drbg,state, 16, out, CCDRBG_MAX_PSINPUT_SIZE+1, s32);
|
||
rc2|=ok2(rc!=0, "drbg generate: max personalization string length test failed");
|
||
|
||
return rc2;
|
||
}
|
||
|
||
static uint32_t largest(uint32_t a, uint32_t b, uint32_t c)
|
||
{
|
||
if( a>b && a>c )
|
||
return a;
|
||
if(b>c)
|
||
return b;
|
||
else
|
||
return c;
|
||
}
|
||
|
||
static int drbg_stress_test( ccdrbg_factory_t ccdrbg_factory, void *custom)
|
||
{
|
||
|
||
struct ccdrbg_info drbg;
|
||
int rc=-1;
|
||
struct ccdrbg_state *state;
|
||
char *buf, *out;
|
||
out=buf=NULL;
|
||
|
||
ccdrbg_factory(&drbg, custom);
|
||
char b[drbg.size]; state = (struct ccdrbg_state *) b;
|
||
|
||
uint32_t n = largest(CCDRBG_MAX_ENTROPY_SIZE, CCDRBG_MAX_ADDITIONALINPUT_SIZE, CCDRBG_MAX_PSINPUT_SIZE);
|
||
cc_assert(n <((uint32_t)1<<30));
|
||
buf = malloc(n); cc_require(buf!=NULL, end);
|
||
out = malloc(CCDRBG_MAX_REQUEST_SIZE); cc_require(out!=NULL, end);
|
||
|
||
rc = ccdrbg_init(&drbg, state, CCDRBG_MAX_ENTROPY_SIZE-1, buf, CCDRBG_MAX_ENTROPY_SIZE-1, buf, CCDRBG_MAX_PSINPUT_SIZE-1, buf);
|
||
rc |= ccdrbg_generate(&drbg,state, CCDRBG_MAX_REQUEST_SIZE-1, out, CCDRBG_MAX_ADDITIONALINPUT_SIZE-1, buf);
|
||
rc |= drbg.reseed (state, CCDRBG_MAX_ENTROPY_SIZE-1, buf, CCDRBG_MAX_ADDITIONALINPUT_SIZE-1, buf);
|
||
rc |= ccdrbg_generate(&drbg,state, CCDRBG_MAX_REQUEST_SIZE-1, out, CCDRBG_MAX_ADDITIONALINPUT_SIZE-1, buf);
|
||
|
||
end:
|
||
free(buf);
|
||
free(out);
|
||
|
||
return rc;
|
||
}
|
||
|
||
static int drbg_all_limits_test( ccdrbg_factory_t ccdrbg_factory, void *custom)
|
||
{
|
||
int rc;
|
||
|
||
rc = drbg_init_limits_test(ccdrbg_factory, custom);
|
||
rc |= drbg_generate_limits_test(ccdrbg_factory, custom);
|
||
rc |= drbg_reseed_limits_test(ccdrbg_factory, custom);
|
||
ok(rc==0, "drbg limit test failed");
|
||
|
||
rc = drbg_stress_test(ccdrbg_factory, custom);
|
||
ok(rc==0, "drbg stress tst failed");
|
||
|
||
return rc;
|
||
}
|
||
|
||
int ccdrbg_limits_test(void)
|
||
{
|
||
int rc;
|
||
struct ccdrbg_nistctr_custom ctr_custom = {
|
||
.ctr_info = ccaes_ctr_crypt_mode(),
|
||
.keylen = 16,
|
||
.strictFIPS = 1,
|
||
.use_df = 1,
|
||
};
|
||
|
||
struct ccdrbg_nisthmac_custom mac_custom = {
|
||
.di = ccsha256_di(),
|
||
.strictFIPS = 1,
|
||
};
|
||
|
||
#if CORECRYPTO_DEBUG
|
||
diag("Negative test");
|
||
#endif
|
||
// generates 3 error messages"
|
||
rc = drbg_all_limits_test((ccdrbg_factory_t)ccdrbg_factory_nistctr, &ctr_custom);
|
||
rc |= drbg_all_limits_test((ccdrbg_factory_t)ccdrbg_factory_nisthmac, &mac_custom);
|
||
|
||
#if CORECRYPTO_DEBUG
|
||
diag("End of negative tests");
|
||
#endif
|
||
|
||
return rc;
|
||
}
|
||
|
||
|
||
|
||
|