1 /* Copyright (C) 2014 mod_auth_gssapi authors - See COPYING for (C) terms */
3 #include <openssl/evp.h>
4 #include <openssl/hmac.h>
5 #include <openssl/rand.h>
12 const EVP_CIPHER *cipher;
16 apr_status_t SEAL_KEY_CREATE(apr_pool_t *p, struct seal_key **skey,
23 n = apr_pcalloc(p, sizeof(*n));
24 if (!n) return ENOMEM;
26 n->cipher = EVP_aes_256_gcm();
32 keylen = n->cipher->key_len;
34 n->ekey = apr_palloc(p, keylen);
41 if (key->length < keylen) {
45 memcpy(n->ekey, key->value, keylen);
47 ret = apr_generate_random_bytes(n->ekey, keylen);
65 apr_status_t SEAL_BUFFER(apr_pool_t *p, struct seal_key *skey,
66 struct databuf *plain, struct databuf *cipher)
68 apr_status_t err = EFAULT;
69 EVP_CIPHER_CTX ctx = {};
74 EVP_CIPHER_CTX_init(&ctx);
76 /* Add space for padding, IV and tag. */
77 minlen = plain->length / skey->cipher->block_size + 1;
78 minlen *= skey->cipher->block_size;
79 minlen += skey->cipher->iv_len + TAGSIZE;
80 if (cipher->length < minlen) {
81 cipher->length = minlen;
82 cipher->value = apr_palloc(p, cipher->length);
90 ret = apr_generate_random_bytes(cipher->value, skey->cipher->iv_len);
91 if (ret != 0) goto done;
92 cipher->length = skey->cipher->iv_len;
94 ret = EVP_EncryptInit_ex(&ctx, skey->cipher, NULL,
95 skey->ekey, cipher->value);
96 if (ret != 1) goto done;
98 /* Encrypt the data. */
100 ret = EVP_EncryptUpdate(&ctx, &cipher->value[cipher->length],
101 &outlen, plain->value, plain->length);
102 if (ret != 1) goto done;
103 cipher->length += outlen;
106 ret = EVP_EncryptFinal_ex(&ctx, &cipher->value[cipher->length], &outlen);
107 if (ret != 1) goto done;
108 cipher->length += outlen;
111 ret = EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, TAGSIZE,
112 &cipher->value[cipher->length]);
113 if (ret != 1) goto done;
114 cipher->length += TAGSIZE;
119 EVP_CIPHER_CTX_cleanup(&ctx);
123 apr_status_t UNSEAL_BUFFER(apr_pool_t *p, struct seal_key *skey,
124 struct databuf *cipher, struct databuf *plain)
126 apr_status_t err = EFAULT;
127 EVP_CIPHER_CTX ctx = {};
131 EVP_CIPHER_CTX_init(&ctx);
133 if (plain->length < cipher->length - skey->cipher->iv_len - TAGSIZE) {
134 plain->length = cipher->length - skey->cipher->iv_len - TAGSIZE;
135 plain->value = apr_palloc(p, plain->length);
142 ret = EVP_DecryptInit_ex(&ctx, skey->cipher, NULL,
143 skey->ekey, cipher->value);
144 if (ret != 1) goto done;
148 ret = EVP_DecryptUpdate(&ctx, plain->value, &outlen,
149 &cipher->value[skey->cipher->iv_len],
150 cipher->length - skey->cipher->iv_len - TAGSIZE);
151 if (ret != 1) goto done;
152 plain->length += outlen;
154 ret = EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, TAGSIZE,
155 &cipher->value[cipher->length - TAGSIZE]);
156 if (ret != 1) goto done;
159 ret = EVP_DecryptFinal_ex(&ctx, &plain->value[plain->length], &outlen);
160 if (ret != 1) goto done;
161 plain->length += outlen;
166 EVP_CIPHER_CTX_cleanup(&ctx);