- // FIPS 186-2 Sec. 3.1 as modified by Change 1, section entitled "General Purpose Random Number Generation"
- //
-
- static byte_t t[SHA_DIGEST_LENGTH] = {
- 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89,
- 0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76,
- 0xc3, 0xd2, 0xe1, 0xf0
- };
-
- byte_t sha_buf0[SHA_DIGEST_LENGTH];
- byte_t sha_buf1[SHA_DIGEST_LENGTH];
- SHA_CTX SHA;
- BN_CTX* ctx1 = BN_CTX_new(); // used by BN_* functions
- assert(ctx1);
-
- // create the 2^160 constant
- BIGNUM c_2powb, c_2, c_160;
- BN_init(&c_2powb); BN_init(&c_2); BN_init(&c_160);
- BN_set_word(&c_2, 2);
- BN_set_word(&c_160, 160);
- BN_exp(&c_2powb, &c_2, &c_160, ctx1);
-
- // ROUND 1
- // step a -- SMPTE 429.6 sets XSEED = 0, so no need to do anything for this step
- // step b -- (key mod 2^160) is moot because the input value is only 128 bits in length
-
- // step c -- x = G(t,xkey)
- SHA1_Init(&SHA);
- SHA1_Update(&SHA, t, SHA_DIGEST_LENGTH);
- SHA1_Update(&SHA, key, KeyLen);
- SHA1_Final(sha_buf0, &SHA);
-
- // step d ...
- BIGNUM xkey1, xkey2, x0;
- BN_init(&xkey1); BN_init(&xkey2); BN_init(&x0);
-
- BN_bin2bn(key, KeyLen, &xkey1);
- BN_bin2bn(sha_buf0, SHA_DIGEST_LENGTH, &x0);
- BN_add_word(&xkey1, 1); // xkey += 1
- BN_add(&xkey2, &xkey1, &x0); // xkey += x
- BN_mod(&xkey1, &xkey2, &c_2powb, ctx1); // xkey = xkey mod (2^160)
-
- // ROUND 2
- // step a -- SMPTE 429.6 sets XSEED = 0, so no need to do anything for this step
- // step b -- (key mod 2^160) is moot because xkey1 is the result of the same operation
-
- byte_t bin_buf[SHA_DIGEST_LENGTH+1]; // we need xkey1 in bin form for use by SHA1_Update
- ui32_t bin_buf_len = BN_num_bytes(&xkey1);
- assert(bin_buf_len < SHA_DIGEST_LENGTH+1);
- BN_bn2bin(&xkey1, bin_buf);
-
- // step c -- x = G(t,xkey)
- SHA1_Init(&SHA);
- SHA1_Update(&SHA, t, SHA_DIGEST_LENGTH);
- SHA1_Update(&SHA, bin_buf, bin_buf_len);
- SHA1_Final(sha_buf1, &SHA);
-
- assert(memcmp(sha_buf1, sha_buf0, SHA_DIGEST_LENGTH) != 0); // are x0 and x1 different?
-
- BN_CTX_free(ctx1);
- memcpy(m_key, sha_buf1, KeyLen);