int cgc_bn_cgc_random(bn_t *bn, const bn_t *max, rng_t *rng) { unsigned int bits = cgc_bn_length(max); cgc_bn_destroy(bn); if (cgc_bn_init_bits(bn, bits) != SUCCESS) return FAILURE; do { // fill with random bytes if (rng_get_bytes(rng, (unsigned char *)bn->data, bn->length * sizeof(uint32_t)) != SUCCESS) goto fail; // apply mask if (bits % 32) bn->data[bits / 32] &= ~((1 << (bits % 32)) - 1); // make sure that this is less than max } while (cgc_bn_cmp(bn, max) >= 0); return SUCCESS; fail: cgc_bn_destroy(bn); return FAILURE; }
/** Create a PRNG from a RNG In case you pass bits as '-1' the PRNG will be setup as if the export/import functionality has been used, but the imported data comes directly from the RNG. @param bits Number of bits of entropy desired (-1 or 64 ... 1024) @param wprng Index of which PRNG to setup @param prng [out] PRNG state to initialize @param callback A pointer to a void function for when the RNG is slow, this can be NULL @return CRYPT_OK if successful */ int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)) { unsigned char* buf; unsigned long bytes; int err; LTC_ARGCHK(prng != NULL); /* check parameter */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if (bits == -1) { bytes = prng_descriptor[wprng].export_size; } else if (bits < 64 || bits > 1024) { return CRYPT_INVALID_PRNGSIZE; } else { bytes = (unsigned long)((bits+7)/8) * 2; } if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) { return err; } buf = XMALLOC(bytes); if (buf == NULL) { return CRYPT_MEM; } if (rng_get_bytes(buf, bytes, callback) != bytes) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } if (bits == -1) { if ((err = prng_descriptor[wprng].pimport(buf, bytes, prng)) != CRYPT_OK) { goto LBL_ERR; } } else { if ((err = prng_descriptor[wprng].add_entropy(buf, bytes, prng)) != CRYPT_OK) { goto LBL_ERR; } } if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) { goto LBL_ERR; } LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf, bytes); #endif XFREE(buf); return err; }
SgObject Sg_ReadSysRandom(int bits) { SgObject buf; bits = (bits/8)+((bits%8)!=0?1:0); buf = Sg_MakeByteVector(bits, 0); if (rng_get_bytes(SG_BVECTOR_ELEMENTS(buf), (unsigned long)bits, NULL) != (unsigned long)bits) { Sg_Error(UC("failed to read system prng")); } return buf; }
int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)) { unsigned char buf[256]; int err; _ARGCHK(prng != NULL); /* check parameter */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if (bits < 64 || bits > 1024) { return CRYPT_INVALID_PRNGSIZE; } if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) { return err; } bits = ((bits/8)+((bits&7)!=0?1:0)) * 2; if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) { return CRYPT_ERROR_READPRNG; } if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) { return err; } if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) { return err; } #ifdef CLEAN_STACK zeromem(buf, sizeof(buf)); #endif return CRYPT_OK; }
/** Read from the PRNG @param out Destination @param outlen Length of output @param prng The active PRNG to read from @return Number of octets read */ unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng) { LTC_ARGCHK(out != NULL); return rng_get_bytes(out, outlen, NULL); }
/* * The main routine. Mostly validate cmdline params, open files, run the KDF, * and do the crypt. */ int main(int argc, char *argv[]) { unsigned char salt[SALT_LENGTH]; FILE *infd = NULL, *outfd = NULL; int encrypt = -1; int hash = -1; int ret; unsigned char keyiv[KEY_LENGTH + IV_LENGTH]; unsigned long keyivlen = (KEY_LENGTH + IV_LENGTH); unsigned char *key, *iv; /* Check proper number of cmdline args */ if(argc < 5 || argc > 6) BARF("Invalid number of arguments"); /* Check proper mode of operation */ if (!strncmp(argv[1], "enc", 3)) encrypt = 1; else if(!strncmp(argv[1], "dec", 3)) encrypt = 0; else BARF("Bad command name"); /* Check we can open infile/outfile */ infd = fopen(argv[2], "rb"); if(infd == NULL) BARF("Could not open infile"); outfd = fopen(argv[3], "wb"); if(outfd == NULL) BARF("Could not open outfile"); /* Get the salt from wherever */ if(argc == 6) { /* User-provided */ if(parse_hex_salt((unsigned char*) argv[5], salt) != CRYPT_OK) BARF("Bad user-specified salt"); } else if(!strncmp(argv[1], "enc", 3)) { /* Encrypting; get from RNG */ if(rng_get_bytes(salt, sizeof(salt), NULL) != sizeof(salt)) BARF("Not enough random data"); } else { /* Parse from infile (decrypt only) */ if(parse_openssl_header(infd, salt) != CRYPT_OK) BARF("Invalid OpenSSL header in infile"); } /* Fetch the MD5 hasher for PKCS#5 */ hash = register_hash(&md5_desc); if(hash == -1) BARF("Could not register MD5 hash"); /* Set things to a sane initial state */ zeromem(keyiv, sizeof(keyiv)); key = keyiv + 0; /* key comes first */ iv = keyiv + KEY_LENGTH; /* iv comes next */ /* Run the key derivation from the provided passphrase. This gets us the key and iv. */ ret = pkcs_5_alg1_openssl((unsigned char*)argv[4], strlen(argv[4]), salt, OPENSSL_ITERATIONS, hash, keyiv, &keyivlen ); if(ret != CRYPT_OK) BARF("Could not derive key/iv from passphrase"); /* Display the salt/key/iv like OpenSSL cmdline does when -p */ printf("salt="); dump_bytes(salt, sizeof(salt)); printf("\n"); printf("key="); dump_bytes(key, KEY_LENGTH); printf("\n"); printf("iv ="); dump_bytes(iv, IV_LENGTH ); printf("\n"); /* If we're encrypting, write the salt header as OpenSSL does */ if(!strncmp(argv[1], "enc", 3)) { if(fwrite(salt_header, 1, sizeof(salt_header), outfd) != sizeof(salt_header) ) BARF("Error writing salt header to outfile"); if(fwrite(salt, 1, sizeof(salt), outfd) != sizeof(salt)) BARF("Error writing salt to outfile"); } /* At this point, the files are open, the salt has been figured out, and we're ready to pump data through crypt. */ /* Do the crypt operation */ if(do_crypt(infd, outfd, key, iv, encrypt) != CRYPT_OK) BARF("Error during crypt operation"); /* Clean up */ fclose(infd); fclose(outfd); return 0; }