/** PRNG self-test @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled */ int rc4_test(void) { #if !defined(LTC_TEST) || defined(LTC_VALGRIND) return CRYPT_NOP; #else static const struct { unsigned char key[8], pt[8], ct[8]; } tests[] = { { { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 } } }; prng_state prng; unsigned char dst[8]; int err, x; for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { if ((err = rc4_start(&prng)) != CRYPT_OK) { return err; } if ((err = rc4_add_entropy(tests[x].key, 8, &prng)) != CRYPT_OK) { return err; } if ((err = rc4_ready(&prng)) != CRYPT_OK) { return err; } XMEMCPY(dst, tests[x].pt, 8); if (rc4_read(dst, 8, &prng) != 8) { return CRYPT_ERROR_READPRNG; } rc4_done(&prng); if (XMEMCMP(dst, tests[x].ct, 8)) { #if 0 int y; printf("\n\nRC4 failed, I got:\n"); for (y = 0; y < 8; y++) printf("%02x ", dst[y]); printf("\n"); #endif return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif }
/** Export the PRNG state @param out [out] Destination @param outlen [in/out] Max size and resulting size of the state @param prng The PRNG to export @return CRYPT_OK if successful */ int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng) { LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(prng != NULL); if (*outlen < 32) { return CRYPT_BUFFER_OVERFLOW; } if (rc4_read(out, 32, prng) != 32) { return CRYPT_ERROR_READPRNG; } *outlen = 32; return CRYPT_OK; }