+ /*
+ * RSA is vulnerable to timing attacks. Generate a random blinding
+ * factor to protect against this kind of attack.
+ */
+ ret = -E_BLINDING;
+ if (RSA_blinding_on(priv->rsa, NULL) == 0)
+ goto out;
+ ret = RSA_private_decrypt(inlen, inbuf, outbuf, priv->rsa,
+ RSA_PKCS1_OAEP_PADDING);
+ RSA_blinding_off(priv->rsa);
+ if (ret <= 0)
+ ret = -E_DECRYPT;
+out:
+ free_asymmetric_key(priv);
+ return ret;
+}
+
+int pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
+ unsigned len, unsigned char *outbuf)
+{
+ int ret, flen = len; /* RSA_public_encrypt expects a signed int */
+
+ if (flen < 0)
+ return -E_ENCRYPT;
+ ret = RSA_public_encrypt(flen, inbuf, outbuf, pub->rsa,
+ RSA_PKCS1_OAEP_PADDING);
+ return ret < 0? -E_ENCRYPT : ret;
+}
+
+struct aes_ctr_128_context {
+ AES_KEY key;
+ unsigned char ivec[AES_CRT128_BLOCK_SIZE];
+ unsigned char ecount[AES_CRT128_BLOCK_SIZE];
+ unsigned int num;
+};
+
+struct stream_cipher {
+ bool use_aes;
+ union {
+ RC4_KEY rc4_key;
+ struct aes_ctr_128_context aes;
+ } context;
+};
+
+struct stream_cipher *sc_new(const unsigned char *data, int len,
+ bool use_aes)
+{
+ int ret;
+ struct stream_cipher *sc = para_malloc(sizeof(*sc));
+ struct aes_ctr_128_context *aes;
+
+ sc->use_aes = use_aes;
+ if (!use_aes) {
+ RC4_set_key(&sc->context.rc4_key, len, data);
+ return sc;
+ }
+ assert(len >= 2 * AES_CRT128_BLOCK_SIZE);
+ aes = &sc->context.aes;
+ ret = AES_set_encrypt_key(data, AES_CRT128_BLOCK_SIZE * 8 /* bits */,
+ &aes->key);
+ assert(ret == 0);
+ memcpy(aes->ivec, data + AES_CRT128_BLOCK_SIZE, AES_CRT128_BLOCK_SIZE);
+ aes->num = 0;
+ return sc;
+}
+
+void sc_free(struct stream_cipher *sc)
+{
+ free(sc);