I redownloaded /usr/src. I made sample code using libcrypto. I won't even compile now.
Is this some way to prevent user programs from digging into the internal structures? I want to reuse the working “iv” for further transactions. Is that not going to be possible? If you finish a transmission and start again, will you be able to reuse the working iv, or will it default to the original? -Luke -- -Luke
/* struct evp_cipher_ctx_st { const EVP_CIPHER *cipher; ENGINE *engine; int encrypt; int buf_len; unsigned char oiv[EVP_MAX_IV_LENGTH]; // original iv unsigned char iv[EVP_MAX_IV_LENGTH]; // working iv unsigned char buf[EVP_MAX_BLOCK_LENGTH]; int num; void *app_data; int key_len; unsigned long flags; void *cipher_data; int final_used; int block_mask; unsigned char final[EVP_MAX_BLOCK_LENGTH]; }; // EVP_CIPHER_CTX */ #include <err.h> #include <openssl/evp.h> #include <string.h> /* KEYSIZE# can be 16(128 bits), 24(192 bits), or 32(256 bits) */ #define KEYSIZE 32 #define IVSIZE 12 #define AADSIZE 32 #define AESGCMTAGLEN 16 int main() { u_char key[KEYSIZE]; u_char ivec[IVSIZE]; int inlen = 20; u_char inbuf[20]; u_char aad[AADSIZE]; u_char outbuf[100]; arc4random_buf(key, KEYSIZE); arc4random_buf(ivec, IVSIZE); arc4random_buf(inbuf, 20); arc4random_buf(aad, AADSIZE); EVP_CIPHER_CTX *CTX = NULL; int tmplen = 0, outlen = 0; CTX = EVP_CIPHER_CTX_new(); if (CTX == NULL) errx(1, "cannot make new cipher context"); if (!EVP_EncryptInit_ex(CTX, EVP_aes_256_gcm(), NULL, NULL, NULL)) err(1, "encrypt set EVP_aes_256_gcm failed"); if (!EVP_CIPHER_CTX_ctrl(CTX, EVP_CTRL_GCM_SET_IVLEN, IVSIZE, NULL)) err(1, "encrypt set ivsize failed"); if (!EVP_EncryptInit_ex(CTX, NULL, NULL, key, ivec)) err(1, "encrypt set key and ivec"); if (EVP_EncryptUpdate(CTX, NULL, &tmplen, aad, AADSIZE) != 1) err(1, "encrypt set aad"); if (!EVP_EncryptUpdate(CTX, outbuf, &outlen, inbuf, inlen)) { EVP_CIPHER_CTX_free(CTX); err(1, "EncryptUpdate1 failed."); } if (!EVP_EncryptFinal_ex(CTX, outbuf + outlen, &tmplen)) { EVP_CIPHER_CTX_free(CTX); err(1, "EncryptFinal failed."); } outlen += tmplen; if (!EVP_CIPHER_CTX_ctrl(CTX, EVP_CTRL_GCM_GET_TAG, AESGCMTAGLEN, outbuf + outlen)) { EVP_CIPHER_CTX_free(CTX); err(1, "EVP_CTRL_GCM_GET_TAG failed."); } memcpy(ivec, CTX->iv, IVSIZE); EVP_CIPHER_CTX_free(CTX); return outlen + AESGCMTAGLEN; }