static int scryptenc_setup(uint8_t header[96], uint8_t dk[64], const uint8_t * passwd, size_t passwdlen, size_t maxmem, double maxmemfrac, double maxtime) { uint8_t salt[32]; uint8_t hbuf[32]; int logN; uint64_t N; uint32_t r; uint32_t p; SHA256_CTX ctx; uint8_t * key_hmac = &dk[32]; HMAC_SHA256_CTX hctx; int rc; /* Pick values for N, r, p. */ if ((rc = pickparams(maxmem, maxmemfrac, maxtime, &logN, &r, &p)) != 0) return (rc); N = (uint64_t)(1) << logN; /* Get some salt. */ if (crypto_entropy_read(salt, 32)) return (4); /* Generate the derived keys. */ if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64)) return (3); /* Construct the file header. */ memcpy(header, "scrypt", 6); header[6] = 0; header[7] = logN; be32enc(&header[8], r); be32enc(&header[12], p); memcpy(&header[16], salt, 32); /* Add header checksum. */ SHA256_Init(&ctx); SHA256_Update(&ctx, header, 48); SHA256_Final(hbuf, &ctx); memcpy(&header[48], hbuf, 16); /* Add header signature (used for verifying password). */ HMAC_SHA256_Init(&hctx, key_hmac, 32); HMAC_SHA256_Update(&hctx, header, 64); HMAC_SHA256_Final(hbuf, &hctx); memcpy(&header[64], hbuf, 32); /* Success! */ return (0); }
/** * crypto_dh_generate(pub, priv): * Generate a 256-bit private key ${priv}, and compute ${pub} equal to * 2^(2^258 + ${priv}) mod p where p is the Diffie-Hellman group #14 modulus. * Both values are stored as big-endian integers. */ int crypto_dh_generate(uint8_t pub[CRYPTO_DH_PUBLEN], uint8_t priv[CRYPTO_DH_PRIVLEN]) { /* Generate a random private key. */ if (crypto_entropy_read(priv, CRYPTO_DH_PRIVLEN)) goto err0; /* Compute the public key. */ if (crypto_dh_generate_pub(pub, priv)) goto err0; /* Success! */ return (0); err0: /* Failure! */ return (-1); }
/** * crypto_keys_subr_generate_HMAC(key): * Generate an HMAC key. */ int crypto_keys_subr_generate_HMAC(struct crypto_hmac_key ** key) { /* Free any existing key. */ if (*key != NULL) { free((*key)->key); free(*key); } /* Allocate memory. */ if ((*key = malloc(sizeof(struct crypto_hmac_key))) == NULL) goto err0; if (((*key)->key = malloc(32)) == NULL) goto err1; /* Store key length. */ (*key)->len = 32; /* Generate key. */ if (crypto_entropy_read((*key)->key, 32)) { warnp("Could not obtain sufficient entropy"); goto err2; } /* Success! */ return (0); err2: free((*key)->key); err1: free(*key); err0: /* Failure! */ return (-1); }
/** * blinded_modexp(r, a, priv): * Compute ${r} = ${a}^(2^258 + ${priv}), where ${r} and ${priv} are treated * as big-endian integers; and avoid leaking timing data in this process. */ static int blinded_modexp(uint8_t r[CRYPTO_DH_PUBLEN], BIGNUM * a, const uint8_t priv[CRYPTO_DH_PRIVLEN]) { BIGNUM * two_exp_256_bn; BIGNUM * priv_bn; uint8_t blinding[CRYPTO_DH_PRIVLEN]; BIGNUM * blinding_bn; BIGNUM * priv_blinded; BIGNUM * m_bn; BN_CTX * ctx; BIGNUM * r1; BIGNUM * r2; size_t rlen; /* Construct 2^256 in BN representation. */ if ((two_exp_256_bn = BN_bin2bn(two_exp_256, 33, NULL)) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err0; } /* Construct 2^258 + ${priv} in BN representation. */ if ((priv_bn = BN_bin2bn(priv, CRYPTO_DH_PRIVLEN, NULL)) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err1; } if ((!BN_add(priv_bn, priv_bn, two_exp_256_bn)) || (!BN_add(priv_bn, priv_bn, two_exp_256_bn)) || (!BN_add(priv_bn, priv_bn, two_exp_256_bn)) || (!BN_add(priv_bn, priv_bn, two_exp_256_bn))) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err2; } /* Generate blinding exponent. */ if (crypto_entropy_read(blinding, CRYPTO_DH_PRIVLEN)) goto err2; if ((blinding_bn = BN_bin2bn(blinding, CRYPTO_DH_PRIVLEN, NULL)) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err2; } if (!BN_add(blinding_bn, blinding_bn, two_exp_256_bn)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err3; } /* Generate blinded exponent. */ if ((priv_blinded = BN_new()) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err3; } if (!BN_sub(priv_blinded, priv_bn, blinding_bn)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err4; } /* Construct group #14 modulus in BN representation. */ if ((m_bn = BN_bin2bn(crypto_dh_group14, 256, NULL)) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err4; } /* Allocate BN context. */ if ((ctx = BN_CTX_new()) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err5; } /* Allocate space for storing results of exponentiations. */ if ((r1 = BN_new()) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err6; } if ((r2 = BN_new()) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err7; } /* Perform modular exponentiations. */ if (!BN_mod_exp(r1, a, blinding_bn, m_bn, ctx)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err8; } if (!BN_mod_exp(r2, a, priv_blinded, m_bn, ctx)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err8; } /* Compute final result and export to big-endian integer format. */ if (!BN_mod_mul(r1, r1, r2, m_bn, ctx)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err8; } rlen = BN_num_bytes(r1); if (rlen > CRYPTO_DH_PUBLEN) { warn0("Exponent result too large!"); goto err8; } memset(r, 0, CRYPTO_DH_PUBLEN - rlen); BN_bn2bin(r1, r + CRYPTO_DH_PUBLEN - rlen); /* Free space allocated by BN_new. */ BN_clear_free(r2); BN_clear_free(r1); /* Free context allocated by BN_CTX_new. */ BN_CTX_free(ctx); /* Free space allocated by BN_bin2bn. */ BN_free(m_bn); /* Free space allocated by BN_new. */ BN_clear_free(priv_blinded); /* Free space allocated by BN_bin2bn. */ BN_clear_free(blinding_bn); BN_clear_free(priv_bn); BN_free(two_exp_256_bn); /* Success! */ return (0); err8: BN_clear_free(r2); err7: BN_clear_free(r1); err6: BN_CTX_free(ctx); err5: BN_free(m_bn); err4: BN_clear_free(priv_blinded); err3: BN_clear_free(blinding_bn); err2: BN_clear_free(priv_bn); err1: BN_free(two_exp_256_bn); err0: /* Failure! */ return (-1); }
/** * crypto_rsa_sign(key, data, len, sig, siglen): * Sign the provided data with the specified key, writing the signature * into ${sig}. */ int crypto_rsa_sign(int key, const uint8_t * data, size_t len, uint8_t * sig, size_t siglen) { RSA * rsa; /* RSA key used for signing. */ uint8_t mHash[32]; uint8_t salt[32]; uint8_t Mprime[72]; uint8_t H[32]; uint8_t DB[223]; uint8_t dbMask[223]; uint8_t maskedDB[223]; uint8_t EM[256]; size_t i; /* Find the required key. */ if ((rsa = crypto_keys_lookup_RSA(key)) == NULL) goto err0; /* Make sure the key and signature buffer are the correct size. */ if (!crypto_compat_RSA_valid_size(rsa)) { warn0("RSA key is incorrect size"); goto err0; } if (siglen != 256) { warn0("Programmer error: " "signature buffer is incorrect length"); goto err0; } /* Generate mHash as specified in EMSA-PSS-ENCODE from RFC 3447. */ if (crypto_hash_data(CRYPTO_KEY_HMAC_SHA256, data, len, mHash)) { warn0("Programmer error: " "SHA256 should never fail"); goto err0; } /* Generate random salt. */ if (crypto_entropy_read(salt, 32)) { warnp("Could not obtain sufficient entropy"); goto err0; } /* Construct M'. */ memset(Mprime, 0, 8); memcpy(Mprime + 8, mHash, 32); memcpy(Mprime + 40, salt, 32); /* Construct H. */ if (crypto_hash_data(CRYPTO_KEY_HMAC_SHA256, Mprime, 72, H)) { warn0("Programmer error: " "SHA256 should never fail"); goto err0; } /* Construct DB. */ memset(DB, 0, 190); memset(DB + 190, 1, 1); memcpy(DB + 191, salt, 32); /* Construct dbMask and maskedDB. */ crypto_MGF1(H, 32, dbMask, 223); for (i = 0; i < 223; i++) maskedDB[i] = DB[i] ^ dbMask[i]; maskedDB[0] &= 0x7f; /* Construct EM. */ memcpy(EM, maskedDB, 223); memcpy(EM + 223, H, 32); memset(EM + 255, 0xbc, 1); /* Convert EM to a signature, via RSA. */ if (RSA_private_encrypt(256, EM, sig, rsa, RSA_NO_PADDING) != 256) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err0; } /* Success! */ return (0); err0: /* Failure! */ return (-1); }
/** * crypto_rsa_encrypt(key, data, len, out, outlen): * Encrypt the provided data with the specified key, writing the ciphertext * into ${out} (of length ${outlen}). */ int crypto_rsa_encrypt(int key, const uint8_t * data, size_t len, uint8_t * out, size_t outlen) { RSA * rsa; uint8_t lHash[32]; uint8_t DB[223]; uint8_t seed[32]; uint8_t dbMask[223]; uint8_t maskedDB[223]; uint8_t seedMask[32]; uint8_t maskedSeed[32]; uint8_t EM[256]; size_t i; /* Find the required key. */ if ((rsa = crypto_keys_lookup_RSA(key)) == NULL) goto err0; /* Make sure the key and ciphertext buffer are the correct size. */ if (!crypto_compat_RSA_valid_size(rsa)) { warn0("RSA key is incorrect size"); goto err0; } if (outlen != 256) { warn0("Programmer error: " "ciphertext buffer is incorrect length"); goto err0; } /* Make sure the input is not too long. */ if (len > 190) { warn0("Programmer error: " "input to crypto_rsa_encrypt is too long"); goto err0; } /* Construct lHash as specified in RSAES-OAEP-ENCRYPT in RFC 3447. */ if (crypto_hash_data(CRYPTO_KEY_HMAC_SHA256, NULL, 0, lHash)) { warn0("Programmer error: " "SHA256 should never fail"); goto err0; } /* Construct DB. */ memcpy(DB, lHash, 32); memset(DB + 32, 0, 190 - len); memset(DB + 222 - len, 1, 1); memcpy(DB + 223 - len, data, len); /* Generate random seed. */ if (crypto_entropy_read(seed, 32)) { warnp("Could not obtain sufficient entropy"); goto err0; } /* Construct dbMask and maskedDB. */ crypto_MGF1(seed, 32, dbMask, 223); for (i = 0; i < 223; i++) maskedDB[i] = DB[i] ^ dbMask[i]; /* Construct seedMask and maskedSeed. */ crypto_MGF1(maskedDB, 223, seedMask, 32); for (i = 0; i < 32; i++) maskedSeed[i] = seed[i] ^ seedMask[i]; /* Construct EM. */ memset(EM, 0, 1); memcpy(EM + 1, maskedSeed, 32); memcpy(EM + 33, maskedDB, 223); /* Convert EM to ciphertext, via RSA. */ if (RSA_public_encrypt(256, EM, out, rsa, RSA_NO_PADDING) != 256) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err0; } /* Success! */ return (0); err0: /* Failure! */ return (-1); }