- {
- EVP_AES_GCM_CTX *gctx = c->cipher_data;
- switch (type)
- {
- case EVP_CTRL_INIT:
- gctx->key_set = 0;
- gctx->iv_set = 0;
- gctx->ivlen = c->cipher->iv_len;
- gctx->iv = c->iv;
- gctx->taglen = -1;
- gctx->iv_gen = 0;
- gctx->tls_aad_len = -1;
- return 1;
-
- case EVP_CTRL_GCM_SET_IVLEN:
- if (arg <= 0)
- return 0;
- /* Allocate memory for IV if needed */
- if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen))
- {
- if (gctx->iv != c->iv)
- OPENSSL_free(gctx->iv);
- gctx->iv = OPENSSL_malloc(arg);
- if (!gctx->iv)
- return 0;
- }
- gctx->ivlen = arg;
- return 1;
-
- case EVP_CTRL_GCM_SET_TAG:
- if (arg <= 0 || arg > 16 || c->encrypt)
- return 0;
- memcpy(c->buf, ptr, arg);
- gctx->taglen = arg;
- return 1;
-
- case EVP_CTRL_GCM_GET_TAG:
- if (arg <= 0 || arg > 16 || !c->encrypt || gctx->taglen < 0)
- return 0;
- memcpy(ptr, c->buf, arg);
- return 1;
-
- case EVP_CTRL_GCM_SET_IV_FIXED:
- /* Special case: -1 length restores whole IV */
- if (arg == -1)
- {
- memcpy(gctx->iv, ptr, gctx->ivlen);
- gctx->iv_gen = 1;
- return 1;
- }
- /* Fixed field must be at least 4 bytes and invocation field
- * at least 8.
- */
- if ((arg < 4) || (gctx->ivlen - arg) < 8)
- return 0;
- if (arg)
- memcpy(gctx->iv, ptr, arg);
- if (c->encrypt &&
- RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
- return 0;
- gctx->iv_gen = 1;
- return 1;
-
- case EVP_CTRL_GCM_IV_GEN:
- if (gctx->iv_gen == 0 || gctx->key_set == 0)
- return 0;
- CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
- if (arg <= 0 || arg > gctx->ivlen)
- arg = gctx->ivlen;
- memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
- /* Invocation field will be at least 8 bytes in size and
- * so no need to check wrap around or increment more than
- * last 8 bytes.
- */
- ctr64_inc(gctx->iv + gctx->ivlen - 8);
- gctx->iv_set = 1;
- return 1;
-
- case EVP_CTRL_GCM_SET_IV_INV:
- if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt)
- return 0;
- memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
- CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
- gctx->iv_set = 1;
- return 1;
-
- case EVP_CTRL_AEAD_TLS1_AAD:
- /* Save the AAD for later use */
- if (arg != 13)
- return 0;
- memcpy(c->buf, ptr, arg);
- gctx->tls_aad_len = arg;
- {
- unsigned int len=c->buf[arg-2]<<8|c->buf[arg-1];
- /* Correct length for explicit IV */
- len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
- /* If decrypting correct for tag too */
- if (!c->encrypt)
- len -= EVP_GCM_TLS_TAG_LEN;
- c->buf[arg-2] = len>>8;
- c->buf[arg-1] = len & 0xff;
- }
- /* Extra padding: tag appended to record */
- return EVP_GCM_TLS_TAG_LEN;
-
- case EVP_CTRL_COPY:
- {
- EVP_CIPHER_CTX *out = ptr;
- EVP_AES_GCM_CTX *gctx_out = out->cipher_data;
- if (gctx->gcm.key)
- {
- if (gctx->gcm.key != &gctx->ks)
- return 0;
- gctx_out->gcm.key = &gctx_out->ks;
- }
- if (gctx->iv == c->iv)
- gctx_out->iv = out->iv;
- else
- {
- gctx_out->iv = OPENSSL_malloc(gctx->ivlen);
- if (!gctx_out->iv)
- return 0;
- memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
- }
- return 1;
- }
-
- default:
- return -1;
-
- }
- }
+{
+ EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c);
+ switch (type) {
+ case EVP_CTRL_INIT:
+ gctx->key_set = 0;
+ gctx->iv_set = 0;
+ gctx->ivlen = EVP_CIPHER_CTX_iv_length(c);
+ gctx->iv = EVP_CIPHER_CTX_iv_noconst(c);
+ gctx->taglen = -1;
+ gctx->iv_gen = 0;
+ gctx->tls_aad_len = -1;
+ return 1;
+
+ case EVP_CTRL_AEAD_SET_IVLEN:
+ if (arg <= 0)
+ return 0;
+ /* Allocate memory for IV if needed */
+ if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) {
+ if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c))
+ OPENSSL_free(gctx->iv);
+ gctx->iv = OPENSSL_malloc(arg);
+ if (gctx->iv == NULL)
+ return 0;
+ }
+ gctx->ivlen = arg;
+ return 1;
+
+ case EVP_CTRL_AEAD_SET_TAG:
+ if (arg <= 0 || arg > 16 || EVP_CIPHER_CTX_encrypting(c))
+ return 0;
+ memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
+ gctx->taglen = arg;
+ return 1;
+
+ case EVP_CTRL_AEAD_GET_TAG:
+ if (arg <= 0 || arg > 16 || !EVP_CIPHER_CTX_encrypting(c)
+ || gctx->taglen < 0)
+ return 0;
+ memcpy(ptr, EVP_CIPHER_CTX_buf_noconst(c), arg);
+ return 1;
+
+ case EVP_CTRL_GCM_SET_IV_FIXED:
+ /* Special case: -1 length restores whole IV */
+ if (arg == -1) {
+ memcpy(gctx->iv, ptr, gctx->ivlen);
+ gctx->iv_gen = 1;
+ return 1;
+ }
+ /*
+ * Fixed field must be at least 4 bytes and invocation field at least
+ * 8.
+ */
+ if ((arg < 4) || (gctx->ivlen - arg) < 8)
+ return 0;
+ if (arg)
+ memcpy(gctx->iv, ptr, arg);
+ if (EVP_CIPHER_CTX_encrypting(c)
+ && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
+ return 0;
+ gctx->iv_gen = 1;
+ return 1;
+
+ case EVP_CTRL_GCM_IV_GEN:
+ if (gctx->iv_gen == 0 || gctx->key_set == 0)
+ return 0;
+ CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
+ if (arg <= 0 || arg > gctx->ivlen)
+ arg = gctx->ivlen;
+ memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
+ /*
+ * Invocation field will be at least 8 bytes in size and so no need
+ * to check wrap around or increment more than last 8 bytes.
+ */
+ ctr64_inc(gctx->iv + gctx->ivlen - 8);
+ gctx->iv_set = 1;
+ return 1;
+
+ case EVP_CTRL_GCM_SET_IV_INV:
+ if (gctx->iv_gen == 0 || gctx->key_set == 0
+ || EVP_CIPHER_CTX_encrypting(c))
+ return 0;
+ memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
+ CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
+ gctx->iv_set = 1;
+ return 1;
+
+ case EVP_CTRL_AEAD_TLS1_AAD:
+ /* Save the AAD for later use */
+ if (arg != EVP_AEAD_TLS1_AAD_LEN)
+ return 0;
+ memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
+ gctx->tls_aad_len = arg;
+ {
+ unsigned int len =
+ EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8
+ | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1];
+ /* Correct length for explicit IV */
+ if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
+ return 0;
+ len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ /* If decrypting correct for tag too */
+ if (!EVP_CIPHER_CTX_encrypting(c)) {
+ if (len < EVP_GCM_TLS_TAG_LEN)
+ return 0;
+ len -= EVP_GCM_TLS_TAG_LEN;
+ }
+ EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8;
+ EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff;
+ }
+ /* Extra padding: tag appended to record */
+ return EVP_GCM_TLS_TAG_LEN;
+
+ case EVP_CTRL_COPY:
+ {
+ EVP_CIPHER_CTX *out = ptr;
+ EVP_AES_GCM_CTX *gctx_out = EVP_C_DATA(EVP_AES_GCM_CTX,out);
+ if (gctx->gcm.key) {
+ if (gctx->gcm.key != &gctx->ks)
+ return 0;
+ gctx_out->gcm.key = &gctx_out->ks;
+ }
+ if (gctx->iv == EVP_CIPHER_CTX_iv_noconst(c))
+ gctx_out->iv = EVP_CIPHER_CTX_iv_noconst(out);
+ else {
+ gctx_out->iv = OPENSSL_malloc(gctx->ivlen);
+ if (gctx_out->iv == NULL)
+ return 0;
+ memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
+ }
+ return 1;
+ }
+
+ default:
+ return -1;
+
+ }
+}