Commit 47b8f79f authored by Geoff Simmons's avatar Geoff Simmons

Implement "unpadding" in decrypt(), and move padding code to padding.h.

The size of the tests has necessitated a hard-wired setting for the size
of libgcrypt secure memory; a better way to handle lib initialization is
on the to-do list.
parent be622c62
Pipeline #166 skipped
/*-
* Copyright 2017 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
typedef void* pad_f(struct ws *ws, void *src, size_t len, size_t blocklen,
size_t *newlen);
static inline void *
pad(struct ws *ws, void *src, size_t len, size_t blocklen, size_t *newlen,
size_t *padlen)
{
void *dst;
assert(blocklen > 0);
*newlen = ((len + blocklen) / blocklen) * blocklen;
*padlen = *newlen - len;
if ((dst = WS_Alloc(ws, *newlen)) == NULL)
return NULL;
memcpy(dst, src, len);
return dst;
}
static void * __match_proto__(pad_f)
pad_pkcs7(struct ws *ws, void *src, size_t len, size_t blocklen, size_t *newlen)
{
size_t padlen;
unsigned char *dst;
dst = pad(ws, src, len, blocklen, newlen, &padlen);
if (dst == NULL)
return NULL;
for (unsigned i = len; i < *newlen; i++)
dst[i] = padlen;
return dst;
}
static void * __match_proto__(pad_f)
pad_iso7816(struct ws *ws, void *src, size_t len, size_t blocklen,
size_t *newlen)
{
size_t padlen;
unsigned char *dst;
dst = pad(ws, src, len, blocklen, newlen, &padlen);
if (dst == NULL)
return NULL;
dst[len] = 0x80;
for (unsigned i = len + 1; i < *newlen; i++)
dst[i] = 0;
return dst;
}
static void * __match_proto__(pad_f)
pad_x923(struct ws *ws, void *src, size_t len, size_t blocklen, size_t *newlen)
{
size_t padlen;
unsigned char *dst;
dst = pad(ws, src, len, blocklen, newlen, &padlen);
if (dst == NULL)
return NULL;
dst[*newlen - 1] = padlen;
for (unsigned i = len; i < *newlen - 1; i++)
dst[i] = 0;
return dst;
}
static pad_f * const padf[] = {
[PKCS7] = pad_pkcs7,
[ISO7816] = pad_iso7816,
[X923] = pad_x923,
};
typedef int unpadlen_f(void *plaintext, int cipherlen, size_t blocklen);
static int __match_proto__(unpadlen_f)
unpadlen_pkcs7(void *plaintext, int cipherlen, size_t blocklen)
{
assert(((unsigned char *)plaintext)[cipherlen-1] <= blocklen);
assert(((unsigned char *)plaintext)[cipherlen-1] <= cipherlen);
return cipherlen - ((unsigned char *)plaintext)[cipherlen-1];
}
static int __match_proto__(unpadlen_f)
unpadlen_iso7816(void *plaintext, int cipherlen, size_t blocklen)
{
(void) blocklen;
int i = cipherlen - 1;
while (i > 0 && ((unsigned char *)plaintext)[i] != 0x80)
assert(0 == ((unsigned char *)plaintext)[i--]);
return i - 1;
}
static int __match_proto__(unpadlen_f)
unpadlen_x923(void *plaintext, int cipherlen, size_t blocklen)
{
return unpadlen_pkcs7(plaintext, cipherlen, blocklen);
}
static unpadlen_f * const unpadlenf[] = {
[PKCS7] = unpadlen_pkcs7,
[ISO7816] = unpadlen_iso7816,
[X923] = unpadlen_x923,
};
This diff is collapsed.
......@@ -41,6 +41,7 @@
#include "vcc_if.h"
#include "vmod_gcrypt.h"
#include "padding.h"
#define str(s) xstr(s)
#define xstr(s) #s
......@@ -92,78 +93,6 @@ errmsg(VRT_CTX, const char *fmt, ...)
va_end(args);
}
/* Padding functions */
typedef void* pad_f(struct ws *ws, void *src, size_t len, size_t blocklen,
size_t *newlen);
static inline void *
pad(struct ws *ws, void *src, size_t len, size_t blocklen, size_t *newlen,
size_t *padlen)
{
void *dst;
assert(blocklen > 0);
*newlen = ((len + blocklen) / blocklen) * blocklen;
*padlen = *newlen - len;
if ((dst = WS_Alloc(ws, *newlen)) == NULL)
return NULL;
memcpy(dst, src, len);
return dst;
}
static void * __match_proto__(pad_f)
pad_pkcs7(struct ws *ws, void *src, size_t len, size_t blocklen, size_t *newlen)
{
size_t padlen;
unsigned char *dst;
dst = pad(ws, src, len, blocklen, newlen, &padlen);
if (dst == NULL)
return NULL;
for (unsigned i = len; i < *newlen; i++)
dst[i] = padlen;
return dst;
}
static void * __match_proto__(pad_f)
pad_iso7816(struct ws *ws, void *src, size_t len, size_t blocklen,
size_t *newlen)
{
size_t padlen;
unsigned char *dst;
dst = pad(ws, src, len, blocklen, newlen, &padlen);
if (dst == NULL)
return NULL;
dst[len] = 0x80;
for (unsigned i = len + 1; i < *newlen; i++)
dst[i] = 0;
return dst;
}
static void * __match_proto__(pad_f)
pad_x923(struct ws *ws, void *src, size_t len, size_t blocklen, size_t *newlen)
{
size_t padlen;
unsigned char *dst;
dst = pad(ws, src, len, blocklen, newlen, &padlen);
if (dst == NULL)
return NULL;
dst[*newlen - 1] = padlen;
for (unsigned i = len; i < *newlen - 1; i++)
dst[i] = 0;
return dst;
}
static pad_f * const padf[] = {
[PKCS7] = pad_pkcs7,
[ISO7816] = pad_iso7816,
[X923] = pad_x923,
};
/* Event function */
int __match_proto__(vmod_event_f)
......@@ -179,6 +108,7 @@ event(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
return 1;
}
/* XXX other initialization */
gcry_control (GCRYCTL_INIT_SECMEM, 65536, 0);
}
return 0;
}
......@@ -409,6 +339,7 @@ vmod_symmetric_decrypt(VRT_CTX, struct vmod_gcrypt_symmetric *symmetric,
symmetric->vcl_name);
return NULL;
}
assert(ciphertext->len >= 0);
snap = WS_Snapshot(ctx->ws);
if ((plaintext = WS_Alloc(ctx->ws, sizeof(*plaintext))) == NULL) {
......@@ -416,8 +347,9 @@ vmod_symmetric_decrypt(VRT_CTX, struct vmod_gcrypt_symmetric *symmetric,
symmetric->vcl_name);
return NULL;
}
if ((plaintext->priv = WS_Alloc(ctx->ws, ciphertext->len)) == NULL) {
plaintext->priv = WS_Front(ctx->ws);
if (WS_Reserve(ctx->ws, 0) < (unsigned) ciphertext->len) {
VERRNOMEM(ctx, "Allocating plaintext result in %s.decrypt()",
symmetric->vcl_name);
WS_Reset(ctx->ws, snap);
......@@ -429,6 +361,7 @@ vmod_symmetric_decrypt(VRT_CTX, struct vmod_gcrypt_symmetric *symmetric,
if (iv == NULL) {
VERR(ctx, "Required initialization vector is NULL in "
"%s.decrypt()", symmetric->vcl_name);
WS_Release(ctx->ws, 0);
WS_Reset(ctx->ws, snap);
return NULL;
}
......@@ -441,6 +374,7 @@ vmod_symmetric_decrypt(VRT_CTX, struct vmod_gcrypt_symmetric *symmetric,
VERR(ctx, "Cannot set initialization vector in "
"%s.decrypt(): %s/%s", symmetric->vcl_name,
gcry_strsource(err), gcry_strerror(err));
WS_Release(ctx->ws, 0);
WS_Reset(ctx->ws, snap);
return NULL;
}
......@@ -449,6 +383,7 @@ vmod_symmetric_decrypt(VRT_CTX, struct vmod_gcrypt_symmetric *symmetric,
if (ctr == NULL || ctr->priv == NULL) {
VERR(ctx, "Required counter vector is NULL in "
"%s.decrypt()", symmetric->vcl_name);
WS_Release(ctx->ws, 0);
WS_Reset(ctx->ws, snap);
return NULL;
}
......@@ -458,6 +393,7 @@ vmod_symmetric_decrypt(VRT_CTX, struct vmod_gcrypt_symmetric *symmetric,
VERR(ctx, "Cannot set counter vector in %s.decrypt(): "
"%s/%s", symmetric->vcl_name, gcry_strsource(err),
gcry_strerror(err));
WS_Release(ctx->ws, 0);
WS_Reset(ctx->ws, snap);
return NULL;
}
......@@ -467,10 +403,20 @@ vmod_symmetric_decrypt(VRT_CTX, struct vmod_gcrypt_symmetric *symmetric,
!= GPG_ERR_NO_ERROR) {
VERR(ctx, "in %s.decrypt(): %s/%s", symmetric->vcl_name,
gcry_strsource(err), gcry_strerror(err));
WS_Release(ctx->ws, 0);
WS_Reset(ctx->ws, snap);
return NULL;
}
plaintext->len = ciphertext->len;
if (symmetric->padding == NONE)
plaintext->len = ciphertext->len;
else {
assert(plaintext->len % symmetric->blocklen == 0);
plaintext->len =
(unpadlenf[symmetric->padding])(plaintext->priv,
ciphertext->len,
symmetric->blocklen);
}
WS_Release(ctx->ws, plaintext->len);
plaintext->free = NULL;
return plaintext;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment