Replaced system SQLite with SQLCipher to support encrypted database

This commit is contained in:
Oleksii Zghurskyi
2025-06-07 18:11:17 +03:00
parent f4198d62a7
commit 177d74700f
534 changed files with 362771 additions and 21 deletions

View File

@@ -0,0 +1,123 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file adler32.c
Adler-32 checksum algorithm
Written and placed in the public domain by Wei Dai
Adapted for libtomcrypt by Steffen Jaeckel
*/
#ifdef LTC_ADLER32
static const unsigned long s_adler32_base = 65521;
void adler32_init(adler32_state *ctx)
{
LTC_ARGCHKVD(ctx != NULL);
ctx->s[0] = 1;
ctx->s[1] = 0;
}
void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length)
{
unsigned long s1, s2;
LTC_ARGCHKVD(ctx != NULL);
LTC_ARGCHKVD(input != NULL);
s1 = ctx->s[0];
s2 = ctx->s[1];
if (length % 8 != 0) {
do {
s1 += *input++;
s2 += s1;
length--;
} while (length % 8 != 0);
if (s1 >= s_adler32_base) {
s1 -= s_adler32_base;
}
s2 %= s_adler32_base;
}
while (length > 0) {
s1 += input[0];
s2 += s1;
s1 += input[1];
s2 += s1;
s1 += input[2];
s2 += s1;
s1 += input[3];
s2 += s1;
s1 += input[4];
s2 += s1;
s1 += input[5];
s2 += s1;
s1 += input[6];
s2 += s1;
s1 += input[7];
s2 += s1;
length -= 8;
input += 8;
if (s1 >= s_adler32_base) {
s1 -= s_adler32_base;
}
s2 %= s_adler32_base;
}
LTC_ARGCHKVD(s1 < s_adler32_base);
LTC_ARGCHKVD(s2 < s_adler32_base);
ctx->s[0] = (unsigned short)s1;
ctx->s[1] = (unsigned short)s2;
}
void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size)
{
unsigned char* h;
LTC_ARGCHKVD(ctx != NULL);
LTC_ARGCHKVD(hash != NULL);
h = hash;
switch (size) {
default:
h[3] = ctx->s[0] & 0x0ff;
/* FALLTHROUGH */
case 3:
h[2] = (ctx->s[0] >> 8) & 0x0ff;
/* FALLTHROUGH */
case 2:
h[1] = ctx->s[1] & 0x0ff;
/* FALLTHROUGH */
case 1:
h[0] = (ctx->s[1] >> 8) & 0x0ff;
/* FALLTHROUGH */
case 0:
;
}
}
int adler32_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
const void* in = "libtomcrypt";
const unsigned char adler32[] = { 0x1b, 0xe8, 0x04, 0xba };
unsigned char out[4];
adler32_state ctx;
adler32_init(&ctx);
adler32_update(&ctx, in, XSTRLEN(in));
adler32_finish(&ctx, out, 4);
if (compare_testvector(adler32, 4, out, 4, "adler32", 0)) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif
}
#endif

View File

@@ -0,0 +1,65 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file base16_decode.c
Base16/Hex decode a string.
Based on https://stackoverflow.com/a/23898449
Adapted for libtomcrypt by Steffen Jaeckel
*/
#ifdef LTC_BASE16
/**
Base16 decode a string
@param in The Base16 string to decode
@param inlen The length of the Base16 data
@param out [out] The destination of the binary decoded data
@param outlen [in/out] The max size and resulting size of the decoded data
@return CRYPT_OK if successful
*/
int base16_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long pos, out_len;
unsigned char idx0, idx1;
char in0, in1;
const unsigned char hashmap[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */
0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */
0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* @ABCDEFG */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* HIJKLMNO */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* PQRSTUVW */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */
0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* `abcdefg */
};
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
if ((inlen % 2) == 1) return CRYPT_INVALID_PACKET;
out_len = *outlen * 2;
for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < inlen)); pos += 2) {
in0 = in[pos + 0];
in1 = in[pos + 1];
if ((in0 < '0') || (in0 > 'g')) return CRYPT_INVALID_PACKET;
if ((in1 < '0') || (in1 > 'g')) return CRYPT_INVALID_PACKET;
idx0 = (unsigned char) (in0 & 0x1F) ^ 0x10;
idx1 = (unsigned char) (in1 & 0x1F) ^ 0x10;
if (hashmap[idx0] == 0xff) return CRYPT_INVALID_PACKET;
if (hashmap[idx1] == 0xff) return CRYPT_INVALID_PACKET;
out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1];
}
*outlen = pos / 2;
return CRYPT_OK;
}
#endif

View File

@@ -0,0 +1,64 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file base16_encode.c
Base16/Hex encode a string, Steffen Jaeckel
*/
#ifdef LTC_BASE16
/**
Base16 encode a buffer
@param in The input buffer to encode
@param inlen The length of the input buffer
@param out [out] The destination of the Base16 encoded data
@param outlen [in/out] The max size and resulting size of the encoded data
@param options Output 'a-f' on 0 and 'A-F' otherwise.
@return CRYPT_OK if successful
*/
int base16_encode(const unsigned char *in, unsigned long inlen,
char *out, unsigned long *outlen,
unsigned int options)
{
unsigned long i, x;
const char *alphabet;
const char *alphabets[2] = {
"0123456789abcdef",
"0123456789ABCDEF",
};
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
/* check the sizes */
x = inlen * 2 + 1;
if (x < inlen) return CRYPT_OVERFLOW;
if (*outlen < x) {
*outlen = x;
return CRYPT_BUFFER_OVERFLOW;
}
x--;
*outlen = x; /* returning the length without terminating NUL */
if (options == 0) {
alphabet = alphabets[0];
} else {
alphabet = alphabets[1];
}
for (i = 0; i < x; i += 2) {
out[i] = alphabet[(in[i/2] >> 4) & 0x0f];
out[i+1] = alphabet[in[i/2] & 0x0f];
}
out[x] = '\0';
return CRYPT_OK;
}
#endif

View File

@@ -0,0 +1,111 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#ifdef LTC_BASE32
/**
Base32 decode a buffer
@param in The Base32 data to decode
@param inlen The length of the Base32 data
@param out [out] The destination of the binary decoded data
@param outlen [in/out] The max size and resulting size of the decoded data
@param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD
@return CRYPT_OK if successful
*/
int base32_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
base32_alphabet id)
{
unsigned long x;
int y = 0;
ulong64 t = 0;
char c;
const unsigned char *map;
const unsigned char tables[4][43] = {
{ /* id = BASE32_RFC4648 : ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 */
99/*0*/,99/*1*/,26/*2*/,27/*3*/,28/*4*/,29/*5*/,30/*6*/,31/*7*/,99/*8*/,99/*9*/,
99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, 7/*H*/, 8/*I*/, 9/*J*/,10/*K*/,11/*L*/,12/*M*/,
13/*N*/,14/*O*/,15/*P*/,16/*Q*/,17/*R*/,18/*S*/,19/*T*/,20/*U*/,21/*V*/,22/*W*/,23/*X*/,24/*Y*/,25/*Z*/
},
{ /* id = BASE32_BASE32HEX : 0123456789ABCDEFGHIJKLMNOPQRSTUV */
0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/,
99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/,18/*I*/,19/*J*/,20/*K*/,21/*L*/,22/*M*/,
23/*N*/,24/*O*/,25/*P*/,26/*Q*/,27/*R*/,28/*S*/,29/*T*/,30/*U*/,31/*V*/,99/*W*/,99/*X*/,99/*Y*/,99/*Z*/
},
{ /* id = BASE32_ZBASE32 : YBNDRFG8EJKMCPQXOT1UWISZA345H769 */
99/*0*/,18/*1*/,99/*2*/,25/*3*/,26/*4*/,27/*5*/,30/*6*/,29/*7*/, 7/*8*/,31/*9*/,
99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
24/*A*/, 1/*B*/,12/*C*/, 3/*D*/, 8/*E*/, 5/*F*/, 6/*G*/,28/*H*/,21/*I*/, 9/*J*/,10/*K*/,99/*L*/,11/*M*/,
2/*N*/,16/*O*/,13/*P*/,14/*Q*/, 4/*R*/,22/*S*/,17/*T*/,19/*U*/,99/*V*/,20/*W*/,15/*X*/, 0/*Y*/,23/*Z*/
},
{ /* id = BASE32_CROCKFORD : 0123456789ABCDEFGHJKMNPQRSTVWXYZ + O=>0 + IL=>1 */
0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/,
99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/, 1/*I*/,18/*J*/,19/*K*/, 1/*L*/,20/*M*/,
21/*N*/, 0/*O*/,22/*P*/,23/*Q*/,24/*R*/,25/*S*/,26/*T*/,99/*U*/,27/*V*/,28/*W*/,29/*X*/,30/*Y*/,31/*Z*/
}
};
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(id >= BASE32_RFC4648);
LTC_ARGCHK(id <= BASE32_CROCKFORD);
/* ignore all trailing = */
while (inlen > 0 && in[inlen-1] == '=') inlen--;
/* no input, nothing to do */
if (inlen == 0) {
*outlen = 0;
return CRYPT_OK;
}
/* check the size of output buffer */
x = (inlen * 5) / 8;
if (*outlen < x) {
*outlen = x;
return CRYPT_BUFFER_OVERFLOW;
}
*outlen = x;
/* check input data length */
x = inlen % 8;
if (x == 1 || x == 3 || x == 6) {
return CRYPT_INVALID_PACKET;
}
map = tables[id];
for (x = 0; x < inlen; x++) {
c = in[x];
/* convert to upper case */
if ((c >= 'a') && (c <= 'z')) c -= 32;
if (c < '0' || c > 'Z' || map[c-'0'] > 31) {
return CRYPT_INVALID_PACKET;
}
t = (t<<5) | map[c-'0'];
if (++y == 8) {
*out++ = (unsigned char)((t>>32) & 255);
*out++ = (unsigned char)((t>>24) & 255);
*out++ = (unsigned char)((t>>16) & 255);
*out++ = (unsigned char)((t>> 8) & 255);
*out++ = (unsigned char)( t & 255);
y = 0;
t = 0;
}
}
if (y > 0) {
t = t << (5 * (8 - y));
if (y >= 2) *out++ = (unsigned char)((t>>32) & 255);
if (y >= 4) *out++ = (unsigned char)((t>>24) & 255);
if (y >= 5) *out++ = (unsigned char)((t>>16) & 255);
if (y >= 7) *out++ = (unsigned char)((t>> 8) & 255);
}
return CRYPT_OK;
}
#endif

View File

@@ -0,0 +1,86 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#ifdef LTC_BASE32
/**
Base32 encode a buffer
@param in The input buffer to encode
@param inlen The length of the input buffer
@param out [out] The destination of the Base32 encoded data
@param outlen [in/out] The max size and resulting size of the encoded data
@param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD
@return CRYPT_OK if successful
*/
int base32_encode(const unsigned char *in, unsigned long inlen,
char *out, unsigned long *outlen,
base32_alphabet id)
{
unsigned long i, x;
const char *codes;
const char *alphabet[4] = {
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", /* id = BASE32_RFC4648 */
"0123456789ABCDEFGHIJKLMNOPQRSTUV", /* id = BASE32_BASE32HEX */
"ybndrfg8ejkmcpqxot1uwisza345h769", /* id = BASE32_ZBASE32 */
"0123456789ABCDEFGHJKMNPQRSTVWXYZ" /* id = BASE32_CROCKFORD */
};
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(id >= BASE32_RFC4648);
LTC_ARGCHK(id <= BASE32_CROCKFORD);
/* check the size of output buffer +1 byte for terminating NUL */
x = (8 * inlen + 4) / 5 + 1;
if (*outlen < x) {
*outlen = x;
return CRYPT_BUFFER_OVERFLOW;
}
*outlen = x - 1; /* returning the length without terminating NUL */
/* no input, nothing to do */
if (inlen == 0) {
*out = '\0';
return CRYPT_OK;
}
codes = alphabet[id];
x = 5 * (inlen / 5);
for (i = 0; i < x; i += 5) {
*out++ = codes[(in[0] >> 3) & 0x1F];
*out++ = codes[(((in[0] & 0x7) << 2) + (in[1] >> 6)) & 0x1F];
*out++ = codes[(in[1] >> 1) & 0x1F];
*out++ = codes[(((in[1] & 0x1) << 4) + (in[2] >> 4)) & 0x1F];
*out++ = codes[(((in[2] & 0xF) << 1) + (in[3] >> 7)) & 0x1F];
*out++ = codes[(in[3] >> 2) & 0x1F];
*out++ = codes[(((in[3] & 0x3) << 3) + (in[4] >> 5)) & 0x1F];
*out++ = codes[in[4] & 0x1F];
in += 5;
}
if (i < inlen) {
unsigned a = in[0];
unsigned b = (i+1 < inlen) ? in[1] : 0;
unsigned c = (i+2 < inlen) ? in[2] : 0;
unsigned d = (i+3 < inlen) ? in[3] : 0;
*out++ = codes[(a >> 3) & 0x1F];
*out++ = codes[(((a & 0x7) << 2) + (b >> 6)) & 0x1F];
if (i+1 < inlen) {
*out++ = codes[(b >> 1) & 0x1F];
*out++ = codes[(((b & 0x1) << 4) + (c >> 4)) & 0x1F];
}
if (i+2 < inlen) {
*out++ = codes[(((c & 0xF) << 1) + (d >> 7)) & 0x1F];
}
if (i+3 < inlen) {
*out++ = codes[(d >> 2) & 0x1F];
*out++ = codes[((d & 0x3) << 3) & 0x1F];
}
}
*out = '\0';
return CRYPT_OK;
}
#endif

View File

@@ -0,0 +1,231 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file base64_decode.c
Compliant base64 code donated by Wayne Scott (wscott@bitmover.com)
base64 URL Safe variant (RFC 4648 section 5) by Karel Miko
*/
#if defined(LTC_BASE64) || defined (LTC_BASE64_URL)
/* 253 - ignored in "relaxed" + "insane" mode: TAB(9), CR(13), LF(10), space(32)
* 254 - padding character '=' (allowed only at the end)
* 255 - ignored in "insane" mode, but not allowed in "relaxed" + "strict" mode
*/
#if defined(LTC_BASE64)
static const unsigned char map_base64[256] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255,
255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255 };
#endif /* LTC_BASE64 */
#if defined(LTC_BASE64_URL)
static const unsigned char map_base64url[] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255,
255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 63,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255
};
#endif /* LTC_BASE64_URL */
enum {
insane = 0,
strict = 1,
relaxed = 2
};
static int s_base64_decode_internal(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
const unsigned char *map, int mode)
{
unsigned long t, x, y, z;
unsigned char c;
int g;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
g = 0; /* '=' counter */
for (x = y = z = t = 0; x < inlen; x++) {
if ((in[x] == 0) && (x == (inlen - 1)) && (mode != strict)) {
continue; /* allow the last byte to be NUL (relaxed+insane) */
}
c = map[(unsigned char)in[x]&0xFF];
if (c == 254) {
g++;
continue;
}
if (c == 253) {
if (mode == strict) {
return CRYPT_INVALID_PACKET;
}
continue; /* allow to ignore white-spaces (relaxed+insane) */
}
if (c == 255) {
if (mode == insane) {
continue; /* allow to ignore invalid garbage (insane) */
}
return CRYPT_INVALID_PACKET;
}
if ((g > 0) && (mode != insane)) {
/* we only allow '=' to be at the end (strict+relaxed) */
return CRYPT_INVALID_PACKET;
}
t = (t<<6)|c;
if (++y == 4) {
if (z + 3 > *outlen) return CRYPT_BUFFER_OVERFLOW;
out[z++] = (unsigned char)((t>>16)&255);
out[z++] = (unsigned char)((t>>8)&255);
out[z++] = (unsigned char)(t&255);
y = t = 0;
}
}
if (y != 0) {
if (y == 1) return CRYPT_INVALID_PACKET;
#if defined(LTC_BASE64)
if (((y + g) != 4) && (mode == strict) && (map == map_base64)) return CRYPT_INVALID_PACKET;
#endif /* LTC_BASE64 */
t = t << (6 * (4 - y));
if (z + y - 1 > *outlen) return CRYPT_BUFFER_OVERFLOW;
if (y >= 2) out[z++] = (unsigned char) ((t >> 16) & 255);
if (y == 3) out[z++] = (unsigned char) ((t >> 8) & 255);
}
*outlen = z;
return CRYPT_OK;
}
#if defined(LTC_BASE64)
/**
Dangerously relaxed base64 decode a block of memory
@param in The base64 data to decode
@param inlen The length of the base64 data
@param out [out] The destination of the binary decoded data
@param outlen [in/out] The max size and resulting size of the decoded data
@return CRYPT_OK if successful
*/
int base64_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
return s_base64_decode_internal(in, inlen, out, outlen, map_base64, insane);
}
/**
Strict base64 decode a block of memory
@param in The base64 data to decode
@param inlen The length of the base64 data
@param out [out] The destination of the binary decoded data
@param outlen [in/out] The max size and resulting size of the decoded data
@return CRYPT_OK if successful
*/
int base64_strict_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
return s_base64_decode_internal(in, inlen, out, outlen, map_base64, strict);
}
/**
Sane base64 decode a block of memory
@param in The base64 data to decode
@param inlen The length of the base64 data
@param out [out] The destination of the binary decoded data
@param outlen [in/out] The max size and resulting size of the decoded data
@return CRYPT_OK if successful
*/
int base64_sane_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
return s_base64_decode_internal(in, inlen, out, outlen, map_base64, relaxed);
}
#endif /* LTC_BASE64 */
#if defined(LTC_BASE64_URL)
/**
Dangerously relaxed base64 (URL Safe, RFC 4648 section 5) decode a block of memory
@param in The base64 data to decode
@param inlen The length of the base64 data
@param out [out] The destination of the binary decoded data
@param outlen [in/out] The max size and resulting size of the decoded data
@return CRYPT_OK if successful
*/
int base64url_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, insane);
}
/**
Strict base64 (URL Safe, RFC 4648 section 5) decode a block of memory
@param in The base64 data to decode
@param inlen The length of the base64 data
@param out [out] The destination of the binary decoded data
@param outlen [in/out] The max size and resulting size of the decoded data
@return CRYPT_OK if successful
*/
int base64url_strict_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, strict);
}
/**
Sane base64 (URL Safe, RFC 4648 section 5) decode a block of memory
@param in The base64 data to decode
@param inlen The length of the base64 data
@param out [out] The destination of the binary decoded data
@param outlen [in/out] The max size and resulting size of the decoded data
@return CRYPT_OK if successful
*/
int base64url_sane_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, relaxed);
}
#endif /* LTC_BASE64_URL */
#endif

View File

@@ -0,0 +1,159 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file base64_encode.c
Compliant base64 encoder donated by Wayne Scott (wscott@bitmover.com)
base64 URL Safe variant (RFC 4648 section 5) by Karel Miko
*/
#if defined(LTC_BASE64) || defined (LTC_BASE64_URL)
#if defined(LTC_BASE64)
static const char * const codes_base64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#endif /* LTC_BASE64 */
#if defined(LTC_BASE64_URL)
static const char * const codes_base64url =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
#endif /* LTC_BASE64_URL */
enum mode {
nopad = 0,
pad = 1,
lf = 2,
cr = 4,
ssh = 8,
crlf = lf | cr,
};
static int s_base64_encode_internal(const unsigned char *in, unsigned long inlen,
char *out, unsigned long *outlen,
const char *codes, unsigned int mode)
{
unsigned long i, len2, leven, linelen;
char *p;
LTC_ARGCHK(outlen != NULL);
linelen = (mode & ssh) ? 72 : 64;
/* valid output size ? */
len2 = 4 * ((inlen + 2) / 3);
if ((mode & crlf) == lf) {
len2 += len2 / linelen;
} else if ((mode & crlf) == crlf) {
len2 += (len2 / linelen) * 2;
}
if (*outlen < len2 + 1) {
*outlen = len2 + 1;
return CRYPT_BUFFER_OVERFLOW;
}
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
if ((void*)in == out) {
return CRYPT_INVALID_ARG;
}
p = out;
leven = 3*(inlen / 3);
for (i = 0; i < leven; i += 3) {
*p++ = codes[(in[0] >> 2) & 0x3F];
*p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F];
*p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F];
*p++ = codes[in[2] & 0x3F];
in += 3;
if ((p - out) % linelen == 0) {
if (mode & cr) *p++ = '\r';
if (mode & lf) *p++ = '\n';
}
}
/* Pad it if necessary... */
if (i < inlen) {
unsigned a = in[0];
unsigned b = (i+1 < inlen) ? in[1] : 0;
*p++ = codes[(a >> 2) & 0x3F];
*p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F];
if (mode & pad) {
*p++ = (i+1 < inlen) ? codes[(((b & 0xf) << 2)) & 0x3F] : '=';
*p++ = '=';
}
else {
if (i+1 < inlen) *p++ = codes[(((b & 0xf) << 2)) & 0x3F];
}
}
/* append a NULL byte */
*p = '\0';
/* return ok */
*outlen = (unsigned long)(p - out); /* the length without terminating NUL */
return CRYPT_OK;
}
#if defined(LTC_BASE64)
/**
base64 Encode a buffer (NUL terminated)
@param in The input buffer to encode
@param inlen The length of the input buffer
@param out [out] The destination of the base64 encoded data
@param outlen [in/out] The max size and resulting size
@return CRYPT_OK if successful
*/
int base64_encode(const unsigned char *in, unsigned long inlen,
char *out, unsigned long *outlen)
{
return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, pad);
}
/**
base64 Encode a buffer for PEM output
(NUL terminated with line-break at 64 chars)
@param in The input buffer to encode
@param inlen The length of the input buffer
@param out [out] The destination of the base64 encoded data
@param outlen [in/out] The max size and resulting size
@param flags \ref base64_pem_flags
@return CRYPT_OK if successful
*/
int base64_encode_pem(const unsigned char *in, unsigned long inlen,
char *out, unsigned long *outlen,
unsigned int flags)
{
int use_crlf = flags & BASE64_PEM_CRLF ? pad | crlf : pad | lf;
int ssh_style = flags & BASE64_PEM_SSH ? ssh : 0;
return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, ssh_style | use_crlf);
}
#endif /* LTC_BASE64 */
#if defined(LTC_BASE64_URL)
/**
base64 (URL Safe, RFC 4648 section 5) Encode a buffer (NUL terminated)
@param in The input buffer to encode
@param inlen The length of the input buffer
@param out [out] The destination of the base64 encoded data
@param outlen [in/out] The max size and resulting size
@return CRYPT_OK if successful
*/
int base64url_encode(const unsigned char *in, unsigned long inlen,
char *out, unsigned long *outlen)
{
return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, nopad);
}
int base64url_strict_encode(const unsigned char *in, unsigned long inlen,
char *out, unsigned long *outlen)
{
return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, pad);
}
#endif /* LTC_BASE64_URL */
#endif

View File

@@ -0,0 +1,196 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
/**
@file bcrypt.c
bcrypt pbkdf, Steffen Jaeckel
*/
#ifdef LTC_BCRYPT
#define BCRYPT_WORDS 8
#define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4)
static int s_bcrypt_hash(const unsigned char *pt,
const unsigned char *pass, unsigned long passlen,
const unsigned char *salt, unsigned long saltlen,
unsigned char *out, unsigned long *outlen)
{
symmetric_key key;
int err, n;
ulong32 ct[BCRYPT_WORDS];
if ((err = blowfish_setup_with_data(pass, passlen, salt, saltlen, &key)) != CRYPT_OK) {
return err;
}
for (n = 0; n < 64; ++n) {
if ((err = blowfish_expand(salt, saltlen, NULL, 0, &key)) != CRYPT_OK) {
return err;
}
if ((err = blowfish_expand(pass, passlen, NULL, 0, &key)) != CRYPT_OK) {
return err;
}
}
for (n = 0; n < BCRYPT_WORDS; ++n) {
LOAD32H(ct[n], &pt[n*4]);
}
for (n = 0; n < 64; ++n) {
blowfish_enc(ct, BCRYPT_WORDS/2, &key);
}
for (n = 0; n < BCRYPT_WORDS; ++n) {
STORE32L(ct[n], &out[4 * n]);
}
*outlen = sizeof(ct);
#ifdef LTC_CLEAN_STACK
zeromem(&key, sizeof(key));
zeromem(ct, sizeof(ct));
#endif
return CRYPT_OK;
}
static int s_bcrypt_pbkdf_hash(const unsigned char *pass, unsigned long passlen,
const unsigned char *salt, unsigned long saltlen,
unsigned char *out, unsigned long *outlen)
{
const unsigned char pt[] = "OxychromaticBlowfishSwatDynamite";
return s_bcrypt_hash(pt, pass, passlen, salt, saltlen, out, outlen);
}
/**
Compatible to bcrypt_pbkdf() as provided in OpenBSD
@param password The input password (or key)
@param password_len The length of the password (octets)
@param salt The salt (or nonce)
@param salt_len The length of the salt (octets)
@param rounds # of iterations desired [read specs for more]
@param hash_idx The index of the hash desired
@param out [out] The destination for this algorithm
@param outlen [in/out] The desired size of the algorithm output
@return CRYPT_OK if successful
*/
int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len,
const unsigned char *salt, unsigned long salt_len,
unsigned int rounds, int hash_idx,
unsigned char *out, unsigned long *outlen)
{
int err;
ulong32 blkno;
unsigned long left, itts, x, y, hashed_pass_len, step_size, steps, dest, used_rounds;
unsigned char *buf[3], blkbuf[4];
unsigned char *hashed_pass;
LTC_ARGCHK(secret != NULL);
LTC_ARGCHK(salt != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
if ((secret_len == 0) || (salt_len == 0) || (*outlen == 0)) {
return CRYPT_INVALID_ARG;
}
/* test hash IDX */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
return err;
}
/* set default value for rounds if not given */
if (rounds == 0) {
used_rounds = LTC_BCRYPT_DEFAULT_ROUNDS;
} else {
used_rounds = rounds;
}
buf[0] = XMALLOC(MAXBLOCKSIZE * 3);
hashed_pass = XMALLOC(MAXBLOCKSIZE);
if (buf[0] == NULL || hashed_pass == NULL) {
if (hashed_pass != NULL) {
XFREE(hashed_pass);
}
if (buf[0] != NULL) {
XFREE(buf[0]);
}
return CRYPT_MEM;
}
/* buf[1] points to the second block of MAXBLOCKSIZE bytes */
buf[1] = buf[0] + MAXBLOCKSIZE;
buf[2] = buf[1] + MAXBLOCKSIZE;
step_size = (*outlen + BCRYPT_HASHSIZE - 1) / BCRYPT_HASHSIZE;
steps = (*outlen + step_size - 1) / step_size;
hashed_pass_len = MAXBLOCKSIZE;
if ((err = hash_memory(hash_idx, (unsigned char*)secret, secret_len, hashed_pass, &hashed_pass_len)) != CRYPT_OK) {
goto LBL_ERR;
}
left = *outlen;
blkno = 0;
while (left != 0) {
/* increment and store current block number */
++blkno;
STORE32H(blkno, blkbuf);
/* process block number blkno */
zeromem(buf[0], MAXBLOCKSIZE*2);
x = MAXBLOCKSIZE;
if ((err = hash_memory_multi(hash_idx, buf[0], &x,
salt, salt_len,
blkbuf, 4uL,
LTC_NULL)) != CRYPT_OK) {
goto LBL_ERR;
}
y = MAXBLOCKSIZE;
if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) {
goto LBL_ERR;
}
XMEMCPY(buf[2], buf[1], y);
/* now compute repeated and XOR it in buf[2] */
for (itts = 1; itts < used_rounds; ++itts) {
x = MAXBLOCKSIZE;
if ((err = hash_memory(hash_idx, buf[1], y, buf[0], &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y = MAXBLOCKSIZE;
if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) {
goto LBL_ERR;
}
for (x = 0; x < y; x++) {
buf[2][x] ^= buf[1][x];
}
}
/* now emit upto `steps` bytes of buf[2] to output */
steps = MIN(steps, left);
for (y = 0; y < steps; ++y) {
dest = y * step_size + (blkno - 1);
if (dest >= *outlen)
break;
out[dest] = buf[2][y];
}
left -= y;
}
err = CRYPT_OK;
LBL_ERR:
#ifdef LTC_CLEAN_STACK
zeromem(buf[0], MAXBLOCKSIZE*3);
zeromem(hashed_pass, MAXBLOCKSIZE);
#endif
XFREE(hashed_pass);
XFREE(buf[0]);
return err;
}
#endif
#pragma clang diagnostic pop

View File

@@ -0,0 +1,23 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file burn_stack.c
Burn stack, Tom St Denis
*/
/**
Burn some stack memory
@param len amount of stack to burn in bytes
*/
void burn_stack(unsigned long len)
{
unsigned char buf[32];
zeromem(buf, sizeof(buf));
if (len > (unsigned long)sizeof(buf)) {
burn_stack(len - sizeof(buf));
}
}

View File

@@ -0,0 +1,81 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file compare_testvector.c
Function to compare two testvectors and print a (detailed) error-message if required, Steffen Jaeckel
*/
#if defined(LTC_TEST) && defined(LTC_TEST_DBG)
static void s_print_hex(const char* what, const void* v, const unsigned long l)
{
const unsigned char* p = v;
unsigned long x, y = 0, z;
fprintf(stderr, "%s contents: \n", what);
for (x = 0; x < l; ) {
fprintf(stderr, "%02X ", p[x]);
if (!(++x % 16) || x == l) {
if((x % 16) != 0) {
z = 16 - (x % 16);
if(z >= 8)
fprintf(stderr, " ");
for (; z != 0; --z) {
fprintf(stderr, " ");
}
}
fprintf(stderr, " | ");
for(; y < x; y++) {
if((y % 8) == 0)
fprintf(stderr, " ");
if(isgraph(p[y]))
fprintf(stderr, "%c", p[y]);
else
fprintf(stderr, ".");
}
fprintf(stderr, "\n");
}
else if((x % 8) == 0) {
fprintf(stderr, " ");
}
}
}
#endif
/**
Compare two test-vectors
@param is The data as it is
@param is_len The length of is
@param should The data as it should
@param should_len The length of should
@param what The type of the data
@param which The iteration count
@return 0 on equality, -1 or 1 on difference
*/
int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which)
{
int res = 0;
if(is_len != should_len) {
res = is_len > should_len ? -1 : 1;
} else {
res = XMEMCMP(is, should, is_len);
}
#if defined(LTC_TEST) && defined(LTC_TEST_DBG)
if (res != 0) {
fprintf(stderr, "Testvector #%i(0x%x) of %s failed:\n", which, which, what);
s_print_hex("SHOULD", should, should_len);
s_print_hex("IS ", is, is_len);
#if LTC_TEST_DBG > 1
} else {
fprintf(stderr, "Testvector #%i(0x%x) of %s passed!\n", which, which, what);
#endif
}
#else
LTC_UNUSED_PARAM(which);
LTC_UNUSED_PARAM(what);
#endif
return res;
}

View File

@@ -0,0 +1,51 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file copy_or_zeromem.c
Either copy or zero a block of memory in constant time, Steffen Jaeckel
*/
/**
Either copy or zero a block of memory in constant time
@param src The source where to read from
@param dest The destination where to write to
@param len The length of the area to process (octets)
@param coz Copy (on 0) Or Zero (> 0)
*/
void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz)
{
unsigned long y;
#ifdef LTC_FAST
unsigned long z;
LTC_FAST_TYPE fastMask = ~(LTC_FAST_TYPE)0; /* initialize fastMask at all ones */
#endif
unsigned char mask = 0xff; /* initialize mask at all ones */
LTC_ARGCHKVD(src != NULL);
LTC_ARGCHKVD(dest != NULL);
if (coz != 0) coz = 1;
y = 0;
mask *= 1 - coz; /* mask = ( coz ? 0 : 0xff ) */
#ifdef LTC_FAST
fastMask *= 1 - coz;
if (len & ~15) {
for (; y < (len & ~15); y += 16) {
for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) {
*(LTC_FAST_TYPE_PTR_CAST(&dest[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&src[y+z])) & fastMask;
}
}
}
#endif
for (; y < len; y++) {
dest[y] = src[y] & mask;
}
#ifdef LTC_CLEAN_STACK
#ifdef LTC_FAST
fastMask = 0;
#endif
mask = 0;
#endif
}

View File

@@ -0,0 +1,193 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crc32.c
CRC-32 checksum algorithm
Written and placed in the public domain by Wei Dai
Adapted for libtomcrypt by Steffen Jaeckel
*/
#ifdef LTC_CRC32
static const ulong32 CRC32_NEGL = 0xffffffffUL;
#if defined(ENDIAN_LITTLE)
#define CRC32_INDEX(c) (c & 0xff)
#define CRC32_SHIFTED(c) (c >> 8)
#elif defined(ENDIAN_BIG)
#define CRC32_INDEX(c) (c >> 24)
#define CRC32_SHIFTED(c) (c << 8)
#else
#error The existing CRC32 implementation only works properly when the endianness of the target platform is known.
#endif
/* Table of CRC-32's of all single byte values (made by makecrc.c) */
static const ulong32 crc32_m_tab[] =
{
#if defined(ENDIAN_LITTLE)
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
#else
0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L,
0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L,
0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L,
0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L,
0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L,
0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L,
0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L,
0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L,
0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L,
0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L,
0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL,
0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L,
0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L,
0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L,
0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L,
0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L,
0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL,
0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L,
0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL,
0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L,
0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L,
0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L,
0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL,
0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL,
0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L,
0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL,
0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L,
0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL,
0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L,
0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L,
0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L,
0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L,
0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L,
0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL,
0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L,
0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L,
0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L,
0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L,
0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L,
0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L,
0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L,
0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L,
0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL,
0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L,
0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L,
0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L,
0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L,
0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L,
0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL,
0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L,
0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL,
0x8def022dL
#endif
};
void crc32_init(crc32_state *ctx)
{
LTC_ARGCHKVD(ctx != NULL);
ctx->crc = CRC32_NEGL;
}
void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length)
{
ulong32 crc;
LTC_ARGCHKVD(ctx != NULL);
LTC_ARGCHKVD(input != NULL);
crc = ctx->crc;
while (length--) {
crc = crc32_m_tab[CRC32_INDEX(crc) ^ *input++] ^ CRC32_SHIFTED(crc);
}
ctx->crc = crc;
}
void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size)
{
unsigned long i;
unsigned char* h;
ulong32 crc;
LTC_ARGCHKVD(ctx != NULL);
LTC_ARGCHKVD(hash != NULL);
h = hash;
crc = ctx->crc;
crc ^= CRC32_NEGL;
if (size > 4) size = 4;
for (i = 0; i < size; i++) {
h[i] = ((unsigned char*)&(crc))[size-i-1];
}
}
int crc32_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
const void* in = "libtomcrypt";
const unsigned char crc32[] = { 0xb3, 0x73, 0x76, 0xef };
unsigned char out[4];
crc32_state ctx;
crc32_init(&ctx);
crc32_update(&ctx, in, XSTRLEN(in));
crc32_finish(&ctx, out, 4);
if (compare_testvector(crc32, 4, out, 4, "CRC32", 0)) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif
}
#endif

View File

@@ -0,0 +1,577 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt.c
Build strings, Tom St Denis
*/
#define NAME_VALUE(s) #s"="NAME(s)
#define NAME(s) #s
const char *crypt_build_settings =
"LibTomCrypt " SCRYPT " (www.libtom.net)\n"
"LibTomCrypt is public domain software.\n"
#if defined(INCLUDE_BUILD_DATE)
"Built on " __DATE__ " at " __TIME__ "\n"
#endif
"\n\nEndianness: "
#if defined(ENDIAN_NEUTRAL)
"neutral/"
#endif
#if defined(ENDIAN_LITTLE)
"little"
#elif defined(ENDIAN_BIG)
"big"
#endif
#if defined(ENDIAN_32BITWORD)
" (32-bit words)\n"
#elif defined(ENDIAN_64BITWORD)
" (64-bit words)\n"
#else
" (no wordsize defined)\n"
#endif
"Clean stack: "
#if defined(LTC_CLEAN_STACK)
"enabled\n"
#else
"disabled\n"
#endif
"\nCiphers built-in:\n"
#if defined(LTC_BLOWFISH)
" Blowfish\n"
#endif
#if defined(LTC_RC2)
" RC2\n"
#endif
#if defined(LTC_RC5)
" RC5\n"
#endif
#if defined(LTC_RC6)
" RC6\n"
#endif
#if defined(LTC_SAFERP)
" Safer+\n"
#endif
#if defined(LTC_SAFER)
" Safer\n"
#endif
#if defined(LTC_RIJNDAEL)
" Rijndael\n"
#endif
#if defined(LTC_XTEA)
" XTEA\n"
#endif
#if defined(LTC_TWOFISH)
" Twofish "
#if defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES)
"(small, tables, all_tables)\n"
#elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES)
"(small, tables)\n"
#elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_ALL_TABLES)
"(small, all_tables)\n"
#elif defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES)
"(tables, all_tables)\n"
#elif defined(LTC_TWOFISH_SMALL)
"(small)\n"
#elif defined(LTC_TWOFISH_TABLES)
"(tables)\n"
#elif defined(LTC_TWOFISH_ALL_TABLES)
"(all_tables)\n"
#else
"\n"
#endif
#endif
#if defined(LTC_DES)
" DES\n"
" DES-X\n"
" 3DES\n"
#endif
#if defined(LTC_SM4)
" SM4\n"
#endif
#if defined(LTC_CAST5)
" CAST5\n"
#endif
#if defined(LTC_NOEKEON)
" Noekeon\n"
#endif
#if defined(LTC_SKIPJACK)
" Skipjack\n"
#endif
#if defined(LTC_KHAZAD)
" Khazad\n"
#endif
#if defined(LTC_ANUBIS)
" Anubis "
#endif
#if defined(LTC_ANUBIS_TWEAK)
" (tweaked)"
#endif
"\n"
#if defined(LTC_KSEED)
" KSEED\n"
#endif
#if defined(LTC_KASUMI)
" KASUMI\n"
#endif
#if defined(LTC_MULTI2)
" MULTI2\n"
#endif
#if defined(LTC_CAMELLIA)
" Camellia\n"
#endif
#if defined(LTC_IDEA)
" IDEA\n"
#endif
#if defined(LTC_SERPENT)
" Serpent\n"
#endif
#if defined(LTC_TEA)
" TEA\n"
#endif
"Stream ciphers built-in:\n"
#if defined(LTC_CHACHA)
" ChaCha\n"
#endif
#if defined(LTC_SALSA20)
" Salsa20\n"
#endif
#if defined(LTC_XSALSA20)
" XSalsa20\n"
#endif
#if defined(LTC_SOSEMANUK)
" Sosemanuk\n"
#endif
#if defined(LTC_RABBIT)
" Rabbit\n"
#endif
#if defined(LTC_RC4_STREAM)
" RC4\n"
#endif
#if defined(LTC_SOBER128_STREAM)
" SOBER128\n"
#endif
"\nHashes built-in:\n"
#if defined(LTC_SHA3)
" SHA3\n"
#endif
#if defined(LTC_KECCAK)
" KECCAK\n"
#endif
#if defined(LTC_SHA512)
" SHA-512\n"
#endif
#if defined(LTC_SHA384)
" SHA-384\n"
#endif
#if defined(LTC_SHA512_256)
" SHA-512/256\n"
#endif
#if defined(LTC_SHA256)
" SHA-256\n"
#endif
#if defined(LTC_SHA512_224)
" SHA-512/224\n"
#endif
#if defined(LTC_SHA224)
" SHA-224\n"
#endif
#if defined(LTC_TIGER)
" TIGER\n"
#endif
#if defined(LTC_SHA1)
" SHA1\n"
#endif
#if defined(LTC_MD5)
" MD5\n"
#endif
#if defined(LTC_MD4)
" MD4\n"
#endif
#if defined(LTC_MD2)
" MD2\n"
#endif
#if defined(LTC_RIPEMD128)
" RIPEMD128\n"
#endif
#if defined(LTC_RIPEMD160)
" RIPEMD160\n"
#endif
#if defined(LTC_RIPEMD256)
" RIPEMD256\n"
#endif
#if defined(LTC_RIPEMD320)
" RIPEMD320\n"
#endif
#if defined(LTC_WHIRLPOOL)
" WHIRLPOOL\n"
#endif
#if defined(LTC_BLAKE2S)
" BLAKE2S\n"
#endif
#if defined(LTC_BLAKE2B)
" BLAKE2B\n"
#endif
#if defined(LTC_CHC_HASH)
" CHC_HASH\n"
#endif
"\nBlock Chaining Modes:\n"
#if defined(LTC_CFB_MODE)
" CFB\n"
#endif
#if defined(LTC_OFB_MODE)
" OFB\n"
#endif
#if defined(LTC_ECB_MODE)
" ECB\n"
#endif
#if defined(LTC_CBC_MODE)
" CBC\n"
#endif
#if defined(LTC_CTR_MODE)
" CTR\n"
#endif
#if defined(LTC_LRW_MODE)
" LRW"
#if defined(LTC_LRW_TABLES)
" (tables) "
#endif
"\n"
#endif
#if defined(LTC_F8_MODE)
" F8\n"
#endif
#if defined(LTC_XTS_MODE)
" XTS\n"
#endif
"\nMACs:\n"
#if defined(LTC_HMAC)
" HMAC\n"
#endif
#if defined(LTC_OMAC)
" OMAC\n"
#endif
#if defined(LTC_PMAC)
" PMAC\n"
#endif
#if defined(LTC_PELICAN)
" PELICAN\n"
#endif
#if defined(LTC_XCBC)
" XCBC\n"
#endif
#if defined(LTC_F9_MODE)
" F9\n"
#endif
#if defined(LTC_POLY1305)
" POLY1305\n"
#endif
#if defined(LTC_BLAKE2SMAC)
" BLAKE2S MAC\n"
#endif
#if defined(LTC_BLAKE2BMAC)
" BLAKE2B MAC\n"
#endif
"\nENC + AUTH modes:\n"
#if defined(LTC_EAX_MODE)
" EAX\n"
#endif
#if defined(LTC_OCB_MODE)
" OCB\n"
#endif
#if defined(LTC_OCB3_MODE)
" OCB3\n"
#endif
#if defined(LTC_CCM_MODE)
" CCM\n"
#endif
#if defined(LTC_GCM_MODE)
" GCM"
#if defined(LTC_GCM_TABLES)
" (tables) "
#endif
#if defined(LTC_GCM_TABLES_SSE2)
" (SSE2) "
#endif
"\n"
#endif
#if defined(LTC_CHACHA20POLY1305_MODE)
" CHACHA20POLY1305\n"
#endif
#if defined(LTC_SIV_MODE)
" SIV\n"
#endif
"\nPRNG:\n"
#if defined(LTC_YARROW)
" Yarrow ("NAME_VALUE(LTC_YARROW_AES)")\n"
#endif
#if defined(LTC_SPRNG)
" SPRNG\n"
#endif
#if defined(LTC_RC4)
" RC4\n"
#endif
#if defined(LTC_CHACHA20_PRNG)
" ChaCha20\n"
#endif
#if defined(LTC_FORTUNA)
" Fortuna (" NAME_VALUE(LTC_FORTUNA_POOLS) ", "
#if defined(LTC_FORTUNA_RESEED_RATELIMIT_TIMED)
"LTC_FORTUNA_RESEED_RATELIMIT_TIMED"
#else
"LTC_FORTUNA_RESEED_RATELIMIT_STATIC, " NAME_VALUE(LTC_FORTUNA_WD)
#endif
#if defined(LTC_FORTUNA_USE_ENCRYPT_ONLY)
", LTC_FORTUNA_USE_ENCRYPT_ONLY"
#endif
")\n"
#endif
#if defined(LTC_SOBER128)
" SOBER128\n"
#endif
#if defined(LTC_WIN32_BCRYPT)
" WIN32_BCRYPT\n"
#endif
"\nPK Crypto:\n"
#if defined(LTC_MRSA)
" RSA"
#if defined(LTC_RSA_BLINDING) && defined(LTC_RSA_CRT_HARDENING)
" (with blinding and CRT hardening)"
#elif defined(LTC_RSA_BLINDING)
" (with blinding)"
#elif defined(LTC_RSA_CRT_HARDENING)
" (with CRT hardening)"
#endif
"\n"
#endif
#if defined(LTC_MDH)
" DH\n"
#endif
#if defined(LTC_MECC)
" ECC"
#if defined(LTC_ECC_TIMING_RESISTANT)
" (with blinding)"
#endif
"\n"
#endif
#if defined(LTC_MDSA)
" DSA\n"
#endif
#if defined(LTC_CURVE25519)
#if defined(LTC_CURVE25519)
" Ed25519\n"
#endif
#if defined(LTC_CURVE25519)
" X25519\n"
#endif
#endif
#if defined(LTC_PK_MAX_RETRIES)
" "NAME_VALUE(LTC_PK_MAX_RETRIES)"\n"
#endif
"\nMPI (Math):\n"
#if defined(LTC_MPI)
" LTC_MPI\n"
#endif
#if defined(LTM_DESC)
" LTM_DESC\n"
#endif
#if defined(TFM_DESC)
" TFM_DESC\n"
#endif
#if defined(GMP_DESC)
" GMP_DESC\n"
#endif
#if defined(LTC_MILLER_RABIN_REPS)
" "NAME_VALUE(LTC_MILLER_RABIN_REPS)"\n"
#endif
"\nCompiler:\n"
#if defined(_WIN64)
" WIN64 platform detected.\n"
#elif defined(_WIN32)
" WIN32 platform detected.\n"
#endif
#if defined(__CYGWIN__)
" CYGWIN Detected.\n"
#endif
#if defined(__DJGPP__)
" DJGPP Detected.\n"
#endif
#if defined(_MSC_VER)
" MSVC compiler detected.\n"
#endif
#if defined(__clang_version__)
" Clang compiler " __clang_version__ ".\n"
#elif defined(INTEL_CC)
" Intel C Compiler " __VERSION__ ".\n"
#elif defined(__GNUC__) /* clang and icc also define __GNUC__ */
" GCC compiler " __VERSION__ ".\n"
#endif
#if defined(__x86_64__)
" x86-64 detected.\n"
#endif
#if defined(LTC_PPC32)
" PPC32 detected.\n"
#endif
"\nVarious others: "
#if defined(ARGTYPE)
" " NAME_VALUE(ARGTYPE) " "
#endif
#if defined(LTC_ADLER32)
" ADLER32 "
#endif
#if defined(LTC_AES_NI)
" AES-NI "
#endif
#if defined(LTC_BASE64)
" BASE64 "
#endif
#if defined(LTC_BASE64_URL)
" BASE64-URL-SAFE "
#endif
#if defined(LTC_BASE32)
" BASE32 "
#endif
#if defined(LTC_BASE16)
" BASE16 "
#endif
#if defined(LTC_BCRYPT)
" BCRYPT "
" " NAME_VALUE(LTC_BCRYPT_DEFAULT_ROUNDS) " "
#endif
#if defined(LTC_CRC32)
" CRC32 "
#endif
#if defined(LTC_DER)
" DER "
" " NAME_VALUE(LTC_DER_MAX_RECURSION) " "
#endif
#if defined(LTC_PKCS_1)
" PKCS#1 "
#endif
#if defined(LTC_PKCS_5)
" PKCS#5 "
#endif
#if defined(LTC_PKCS_8)
" PKCS#8 "
#endif
#if defined(LTC_PKCS_12)
" PKCS#12 "
#endif
#if defined(LTC_PADDING)
" PADDING "
#endif
#if defined(LTC_HKDF)
" HKDF "
#endif
#if defined(LTC_PBES)
" PBES1 "
" PBES2 "
#endif
#if defined(LTC_PEM)
" PEM "
" " NAME_VALUE(LTC_PEM_DECODE_BUFSZ) " "
" " NAME_VALUE(LTC_PEM_READ_BUFSIZE) " "
#endif
#if defined(LTC_SSH)
" SSH "
#endif
#if defined(LTC_PEM_SSH)
" OpenSSH-PEM "
#endif
#if defined(LTC_DEVRANDOM)
" LTC_DEVRANDOM "
#endif
#if defined(LTC_TRY_URANDOM_FIRST)
" LTC_TRY_URANDOM_FIRST "
#endif
#if defined(LTC_RNG_GET_BYTES)
" LTC_RNG_GET_BYTES "
#endif
#if defined(LTC_RNG_MAKE_PRNG)
" LTC_RNG_MAKE_PRNG "
#endif
#if defined(LTC_PRNG_ENABLE_LTC_RNG)
" LTC_PRNG_ENABLE_LTC_RNG "
#endif
#if defined(LTC_HASH_HELPERS)
" LTC_HASH_HELPERS "
#endif
#if defined(LTC_VALGRIND)
" LTC_VALGRIND "
#endif
#if defined(LTC_TEST)
" LTC_TEST "
#endif
#if defined(LTC_TEST_DBG)
" " NAME_VALUE(LTC_TEST_DBG) " "
#endif
#if defined(LTC_TEST_EXT)
" LTC_TEST_EXT "
#endif
#if defined(LTC_SMALL_CODE)
" LTC_SMALL_CODE "
#endif
#if defined(LTC_NO_FILE)
" LTC_NO_FILE "
#endif
#if defined(LTC_FILE_READ_BUFSIZE)
" " NAME_VALUE(LTC_FILE_READ_BUFSIZE) " "
#endif
#if defined(LTC_FAST)
" LTC_FAST "
#endif
#if defined(LTC_NO_FAST)
" LTC_NO_FAST "
#endif
#if defined(LTC_NO_BSWAP)
" LTC_NO_BSWAP "
#endif
#if defined(LTC_NO_ASM)
" LTC_NO_ASM "
#endif
#if defined(LTC_ROx_BUILTIN)
" LTC_ROx_BUILTIN "
#elif defined(LTC_ROx_ASM)
" LTC_ROx_ASM "
#if defined(LTC_NO_ROLC)
" LTC_NO_ROLC "
#endif
#endif
#if defined(LTC_NO_TEST)
" LTC_NO_TEST "
#endif
#if defined(LTC_NO_TABLES)
" LTC_NO_TABLES "
#endif
#if defined(LTC_PTHREAD)
" LTC_PTHREAD "
#endif
#if defined(LTC_EASY)
" LTC_EASY "
#endif
#if defined(LTC_MECC_ACCEL)
" LTC_MECC_ACCEL "
#endif
#if defined(LTC_MECC_FP)
" LTC_MECC_FP "
#endif
#if defined(LTC_ECC_SHAMIR)
" LTC_ECC_SHAMIR "
#endif
#if defined(LTC_CLOCK_GETTIME)
" LTC_CLOCK_GETTIME "
#endif
"\n"
;

View File

@@ -0,0 +1,17 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_argchk.c
Perform argument checking, Tom St Denis
*/
#if (ARGTYPE == 0)
void crypt_argchk(const char *v, const char *s, int d)
{
fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n",
v, d, s);
abort();
}
#endif

View File

@@ -0,0 +1,15 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_cipher_descriptor.c
Stores the cipher descriptor table, Tom St Denis
*/
struct ltc_cipher_descriptor cipher_descriptor[TAB_SIZE] = {
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
LTC_MUTEX_GLOBAL(ltc_cipher_mutex)

View File

@@ -0,0 +1,24 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_cipher_is_valid.c
Determine if cipher is valid, Tom St Denis
*/
/*
Test if a cipher index is valid
@param idx The index of the cipher to search for
@return CRYPT_OK if valid
*/
int cipher_is_valid(int idx)
{
LTC_MUTEX_LOCK(&ltc_cipher_mutex);
if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) {
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return CRYPT_INVALID_CIPHER;
}
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return CRYPT_OK;
}

View File

@@ -0,0 +1,290 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_constants.c
Make various constants available to dynamic languages
like Python - Larry Bugbee, February 2013
LB - Dec 2013 - revised to include compiler define options
LB - Mar 2014 - added endianness and word size
*/
typedef struct {
const char *name;
const int value;
} crypt_constant;
#define C_STRINGIFY(s) { #s, s }
static const crypt_constant s_crypt_constants[] = {
C_STRINGIFY(CRYPT_OK),
C_STRINGIFY(CRYPT_ERROR),
C_STRINGIFY(CRYPT_NOP),
C_STRINGIFY(CRYPT_INVALID_KEYSIZE),
C_STRINGIFY(CRYPT_INVALID_ROUNDS),
C_STRINGIFY(CRYPT_FAIL_TESTVECTOR),
C_STRINGIFY(CRYPT_BUFFER_OVERFLOW),
C_STRINGIFY(CRYPT_INVALID_PACKET),
C_STRINGIFY(CRYPT_INVALID_PRNGSIZE),
C_STRINGIFY(CRYPT_ERROR_READPRNG),
C_STRINGIFY(CRYPT_INVALID_CIPHER),
C_STRINGIFY(CRYPT_INVALID_HASH),
C_STRINGIFY(CRYPT_INVALID_PRNG),
C_STRINGIFY(CRYPT_MEM),
C_STRINGIFY(CRYPT_PK_TYPE_MISMATCH),
C_STRINGIFY(CRYPT_PK_NOT_PRIVATE),
C_STRINGIFY(CRYPT_INVALID_ARG),
C_STRINGIFY(CRYPT_FILE_NOTFOUND),
C_STRINGIFY(CRYPT_PK_INVALID_TYPE),
C_STRINGIFY(CRYPT_OVERFLOW),
C_STRINGIFY(CRYPT_PK_ASN1_ERROR),
C_STRINGIFY(CRYPT_INPUT_TOO_LONG),
C_STRINGIFY(CRYPT_PK_INVALID_SIZE),
C_STRINGIFY(CRYPT_INVALID_PRIME_SIZE),
C_STRINGIFY(CRYPT_PK_INVALID_PADDING),
C_STRINGIFY(CRYPT_HASH_OVERFLOW),
C_STRINGIFY(PK_PUBLIC),
C_STRINGIFY(PK_PRIVATE),
C_STRINGIFY(LTC_ENCRYPT),
C_STRINGIFY(LTC_DECRYPT),
#ifdef LTC_PKCS_1
{"LTC_PKCS_1", 1},
/* Block types */
C_STRINGIFY(LTC_PKCS_1_EMSA),
C_STRINGIFY(LTC_PKCS_1_EME),
/* Padding types */
C_STRINGIFY(LTC_PKCS_1_V1_5),
C_STRINGIFY(LTC_PKCS_1_OAEP),
C_STRINGIFY(LTC_PKCS_1_PSS),
C_STRINGIFY(LTC_PKCS_1_V1_5_NA1),
#else
{"LTC_PKCS_1", 0},
#endif
#ifdef LTC_PADDING
{"LTC_PADDING", 1},
C_STRINGIFY(LTC_PAD_PKCS7),
#ifdef LTC_RNG_GET_BYTES
C_STRINGIFY(LTC_PAD_ISO_10126),
#endif
C_STRINGIFY(LTC_PAD_ANSI_X923),
C_STRINGIFY(LTC_PAD_ONE_AND_ZERO),
C_STRINGIFY(LTC_PAD_ZERO),
C_STRINGIFY(LTC_PAD_ZERO_ALWAYS),
#else
{"LTC_PADDING", 0},
#endif
#ifdef LTC_MRSA
{"LTC_MRSA", 1},
#else
{"LTC_MRSA", 0},
#endif
#ifdef LTC_MECC
{"LTC_MECC", 1},
C_STRINGIFY(ECC_BUF_SIZE),
C_STRINGIFY(ECC_MAXSIZE),
#else
{"LTC_MECC", 0},
#endif
#ifdef LTC_MDSA
{"LTC_MDSA", 1},
C_STRINGIFY(LTC_MDSA_DELTA),
C_STRINGIFY(LTC_MDSA_MAX_GROUP),
C_STRINGIFY(LTC_MDSA_MAX_MODULUS),
#else
{"LTC_MDSA", 0},
#endif
#ifdef LTC_MILLER_RABIN_REPS
C_STRINGIFY(LTC_MILLER_RABIN_REPS),
#endif
#ifdef LTC_DER
/* DER handling */
{"LTC_DER", 1},
C_STRINGIFY(LTC_ASN1_EOL),
C_STRINGIFY(LTC_ASN1_BOOLEAN),
C_STRINGIFY(LTC_ASN1_INTEGER),
C_STRINGIFY(LTC_ASN1_SHORT_INTEGER),
C_STRINGIFY(LTC_ASN1_BIT_STRING),
C_STRINGIFY(LTC_ASN1_OCTET_STRING),
C_STRINGIFY(LTC_ASN1_NULL),
C_STRINGIFY(LTC_ASN1_OBJECT_IDENTIFIER),
C_STRINGIFY(LTC_ASN1_IA5_STRING),
C_STRINGIFY(LTC_ASN1_PRINTABLE_STRING),
C_STRINGIFY(LTC_ASN1_UTF8_STRING),
C_STRINGIFY(LTC_ASN1_UTCTIME),
C_STRINGIFY(LTC_ASN1_CHOICE),
C_STRINGIFY(LTC_ASN1_SEQUENCE),
C_STRINGIFY(LTC_ASN1_SET),
C_STRINGIFY(LTC_ASN1_SETOF),
C_STRINGIFY(LTC_ASN1_RAW_BIT_STRING),
C_STRINGIFY(LTC_ASN1_TELETEX_STRING),
C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME),
C_STRINGIFY(LTC_ASN1_CUSTOM_TYPE),
C_STRINGIFY(LTC_DER_MAX_RECURSION),
#else
{"LTC_DER", 0},
#endif
#ifdef LTC_CTR_MODE
{"LTC_CTR_MODE", 1},
C_STRINGIFY(CTR_COUNTER_LITTLE_ENDIAN),
C_STRINGIFY(CTR_COUNTER_BIG_ENDIAN),
C_STRINGIFY(LTC_CTR_RFC3686),
#else
{"LTC_CTR_MODE", 0},
#endif
#ifdef LTC_GCM_MODE
C_STRINGIFY(LTC_GCM_MODE_IV),
C_STRINGIFY(LTC_GCM_MODE_AAD),
C_STRINGIFY(LTC_GCM_MODE_TEXT),
#endif
C_STRINGIFY(LTC_MP_LT),
C_STRINGIFY(LTC_MP_EQ),
C_STRINGIFY(LTC_MP_GT),
C_STRINGIFY(LTC_MP_NO),
C_STRINGIFY(LTC_MP_YES),
C_STRINGIFY(MAXBLOCKSIZE),
C_STRINGIFY(TAB_SIZE),
C_STRINGIFY(ARGTYPE),
#ifdef LTM_DESC
{"LTM_DESC", 1},
#else
{"LTM_DESC", 0},
#endif
#ifdef TFM_DESC
{"TFM_DESC", 1},
#else
{"TFM_DESC", 0},
#endif
#ifdef GMP_DESC
{"GMP_DESC", 1},
#else
{"GMP_DESC", 0},
#endif
#ifdef LTC_FAST
{"LTC_FAST", 1},
#else
{"LTC_FAST", 0},
#endif
#ifdef LTC_NO_FILE
{"LTC_NO_FILE", 1},
#else
{"LTC_NO_FILE", 0},
#endif
#ifdef ENDIAN_LITTLE
{"ENDIAN_LITTLE", 1},
#else
{"ENDIAN_LITTLE", 0},
#endif
#ifdef ENDIAN_BIG
{"ENDIAN_BIG", 1},
#else
{"ENDIAN_BIG", 0},
#endif
#ifdef ENDIAN_32BITWORD
{"ENDIAN_32BITWORD", 1},
#else
{"ENDIAN_32BITWORD", 0},
#endif
#ifdef ENDIAN_64BITWORD
{"ENDIAN_64BITWORD", 1},
#else
{"ENDIAN_64BITWORD", 0},
#endif
#ifdef ENDIAN_NEUTRAL
{"ENDIAN_NEUTRAL", 1},
#else
{"ENDIAN_NEUTRAL", 0},
#endif
};
/* crypt_get_constant()
* valueout will be the value of the named constant
* return -1 if named item not found
*/
int crypt_get_constant(const char* namein, int *valueout) {
int i;
int count = sizeof(s_crypt_constants) / sizeof(s_crypt_constants[0]);
for (i=0; i<count; i++) {
if (XSTRCMP(s_crypt_constants[i].name, namein) == 0) {
*valueout = s_crypt_constants[i].value;
return 0;
}
}
return 1;
}
/* crypt_list_all_constants()
* if names_list is NULL, names_list_size will be the minimum
* number of bytes needed to receive the complete names_list
* if names_list is NOT NULL, names_list must be the addr of
* sufficient memory allocated into which the names_list
* is to be written. Also, the value in names_list_size
* sets the upper bound of the number of characters to be
* written.
* a -1 return value signifies insufficient space made available
*/
int crypt_list_all_constants(char *names_list, unsigned int *names_list_size) {
int i;
unsigned int total_len = 0;
char *ptr;
int number_len;
int count = sizeof(s_crypt_constants) / sizeof(s_crypt_constants[0]);
/* calculate amount of memory required for the list */
for (i=0; i<count; i++) {
number_len = snprintf(NULL, 0, "%s,%d\n", s_crypt_constants[i].name, s_crypt_constants[i].value);
if (number_len < 0) {
return -1;
}
total_len += number_len;
}
if (names_list == NULL) {
*names_list_size = total_len;
} else {
if (total_len > *names_list_size) {
return -1;
}
/* build the names list */
ptr = names_list;
for (i=0; i<count; i++) {
number_len = snprintf(ptr, total_len, "%s,%d\n", s_crypt_constants[i].name, s_crypt_constants[i].value);
if (number_len < 0) return -1;
if ((unsigned int)number_len > total_len) return -1;
total_len -= number_len;
ptr += number_len;
}
/* to remove the trailing new-line */
ptr -= 1;
*ptr = 0;
}
return 0;
}

View File

@@ -0,0 +1,29 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_find_cipher.c
Find a cipher in the descriptor tables, Tom St Denis
*/
/**
Find a registered cipher by name
@param name The name of the cipher to look for
@return >= 0 if found, -1 if not present
*/
int find_cipher(const char *name)
{
int x;
LTC_ARGCHK(name != NULL);
LTC_MUTEX_LOCK(&ltc_cipher_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name != NULL && !XSTRCMP(cipher_descriptor[x].name, name)) {
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return x;
}
}
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return -1;
}

View File

@@ -0,0 +1,38 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_find_cipher_any.c
Find a cipher in the descriptor tables, Tom St Denis
*/
/**
Find a cipher flexibly. First by name then if not present by block and key size
@param name The name of the cipher desired
@param blocklen The minimum length of the block cipher desired (octets)
@param keylen The minimum length of the key size desired (octets)
@return >= 0 if found, -1 if not present
*/
int find_cipher_any(const char *name, int blocklen, int keylen)
{
int x;
if(name != NULL) {
x = find_cipher(name);
if (x != -1) return x;
}
LTC_MUTEX_LOCK(&ltc_cipher_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name == NULL) {
continue;
}
if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) {
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return x;
}
}
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return -1;
}

View File

@@ -0,0 +1,28 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_find_cipher_id.c
Find cipher by ID, Tom St Denis
*/
/**
Find a cipher by ID number
@param ID The ID (not same as index) of the cipher to find
@return >= 0 if found, -1 if not present
*/
int find_cipher_id(unsigned char ID)
{
int x;
LTC_MUTEX_LOCK(&ltc_cipher_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].ID == ID) {
x = (cipher_descriptor[x].name == NULL) ? -1 : x;
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return x;
}
}
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return -1;
}

View File

@@ -0,0 +1,28 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_find_hash.c
Find a hash, Tom St Denis
*/
/**
Find a registered hash by name
@param name The name of the hash to look for
@return >= 0 if found, -1 if not present
*/
int find_hash(const char *name)
{
int x;
LTC_ARGCHK(name != NULL);
LTC_MUTEX_LOCK(&ltc_hash_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].name != NULL && XSTRCMP(hash_descriptor[x].name, name) == 0) {
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return x;
}
}
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return -1;
}

View File

@@ -0,0 +1,43 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
/**
@file crypt_find_hash_any.c
Find a hash, Tom St Denis
*/
/**
Find a hash flexibly. First by name then if not present by digest size
@param name The name of the hash desired
@param digestlen The minimum length of the digest size (octets)
@return >= 0 if found, -1 if not present
*/int find_hash_any(const char *name, int digestlen)
{
int x, y, z;
LTC_ARGCHK(name != NULL);
x = find_hash(name);
if (x != -1) return x;
LTC_MUTEX_LOCK(&ltc_hash_mutex);
y = MAXBLOCKSIZE+1;
z = -1;
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].name == NULL) {
continue;
}
if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) {
z = x;
y = hash_descriptor[x].hashsize;
}
}
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return z;
}
#pragma clang diagnostic pop

View File

@@ -0,0 +1,28 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_find_hash_id.c
Find hash by ID, Tom St Denis
*/
/**
Find a hash by ID number
@param ID The ID (not same as index) of the hash to find
@return >= 0 if found, -1 if not present
*/
int find_hash_id(unsigned char ID)
{
int x;
LTC_MUTEX_LOCK(&ltc_hash_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].ID == ID) {
x = (hash_descriptor[x].name == NULL) ? -1 : x;
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return x;
}
}
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return -1;
}

View File

@@ -0,0 +1,23 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_find_hash_oid.c
Find a hash, Tom St Denis
*/
int find_hash_oid(const unsigned long *ID, unsigned long IDlen)
{
int x;
LTC_ARGCHK(ID != NULL);
LTC_MUTEX_LOCK(&ltc_hash_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].name != NULL && hash_descriptor[x].OIDlen == IDlen && !XMEMCMP(hash_descriptor[x].OID, ID, sizeof(unsigned long) * IDlen)) {
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return x;
}
}
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return -1;
}

View File

@@ -0,0 +1,29 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_find_prng.c
Find a PRNG, Tom St Denis
*/
/**
Find a registered PRNG by name
@param name The name of the PRNG to look for
@return >= 0 if found, -1 if not present
*/
int find_prng(const char *name)
{
int x;
LTC_ARGCHK(name != NULL);
LTC_MUTEX_LOCK(&ltc_prng_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if ((prng_descriptor[x].name != NULL) && XSTRCMP(prng_descriptor[x].name, name) == 0) {
LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
return x;
}
}
LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
return -1;
}

View File

@@ -0,0 +1,45 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_fsa.c
LibTomCrypt FULL SPEED AHEAD!, Tom St Denis
*/
/* format is ltc_mp, cipher_desc, [cipher_desc], NULL, hash_desc, [hash_desc], NULL, prng_desc, [prng_desc], NULL */
int crypt_fsa(void *mp, ...)
{
va_list args;
void *p;
va_start(args, mp);
if (mp != NULL) {
XMEMCPY(&ltc_mp, mp, sizeof(ltc_mp));
}
while ((p = va_arg(args, void*)) != NULL) {
if (register_cipher(p) == -1) {
va_end(args);
return CRYPT_INVALID_CIPHER;
}
}
while ((p = va_arg(args, void*)) != NULL) {
if (register_hash(p) == -1) {
va_end(args);
return CRYPT_INVALID_HASH;
}
}
while ((p = va_arg(args, void*)) != NULL) {
if (register_prng(p) == -1) {
va_end(args);
return CRYPT_INVALID_PRNG;
}
}
va_end(args);
return CRYPT_OK;
}

View File

@@ -0,0 +1,15 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_hash_descriptor.c
Stores the hash descriptor table, Tom St Denis
*/
struct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = {
{ NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL, NULL }
};
LTC_MUTEX_GLOBAL(ltc_hash_mutex)

View File

@@ -0,0 +1,24 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_hash_is_valid.c
Determine if hash is valid, Tom St Denis
*/
/*
Test if a hash index is valid
@param idx The index of the hash to search for
@return CRYPT_OK if valid
*/
int hash_is_valid(int idx)
{
LTC_MUTEX_LOCK(&ltc_hash_mutex);
if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) {
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return CRYPT_INVALID_HASH;
}
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return CRYPT_OK;
}

View File

@@ -0,0 +1,81 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_inits.c
Provide math library functions for dynamic languages
like Python - Larry Bugbee, February 2013
*/
#ifdef LTM_DESC
void init_LTM(void)
{
ltc_mp = ltm_desc;
}
#endif
#ifdef TFM_DESC
void init_TFM(void)
{
ltc_mp = tfm_desc;
}
#endif
#ifdef GMP_DESC
void init_GMP(void)
{
ltc_mp = gmp_desc;
}
#endif
int crypt_mp_init(const char* mpi)
{
if (mpi == NULL) return CRYPT_ERROR;
switch (mpi[0]) {
#ifdef LTM_DESC
case 'l':
case 'L':
ltc_mp = ltm_desc;
return CRYPT_OK;
#endif
#ifdef TFM_DESC
case 't':
case 'T':
ltc_mp = tfm_desc;
return CRYPT_OK;
#endif
#ifdef GMP_DESC
case 'g':
case 'G':
ltc_mp = gmp_desc;
return CRYPT_OK;
#endif
#ifdef EXT_MATH_LIB
case 'e':
case 'E':
{
extern ltc_math_descriptor EXT_MATH_LIB;
ltc_mp = EXT_MATH_LIB;
}
#if defined(LTC_TEST_DBG)
#define NAME_VALUE(s) #s"="NAME(s)
#define NAME(s) #s
printf("EXT_MATH_LIB = %s\n", NAME_VALUE(EXT_MATH_LIB));
#undef NAME_VALUE
#undef NAME
#endif
return CRYPT_OK;
#endif
default:
#if defined(LTC_TEST_DBG)
printf("Unknown/Invalid MPI provider: %s\n", mpi);
#endif
return CRYPT_ERROR;
}
}

View File

@@ -0,0 +1,6 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/* Initialize ltc_mp to nulls, to force allocation on all platforms, including macOS. */
ltc_math_descriptor ltc_mp = { 0 };

View File

@@ -0,0 +1,14 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_prng_descriptor.c
Stores the PRNG descriptors, Tom St Denis
*/
struct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = {
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
LTC_MUTEX_GLOBAL(ltc_prng_mutex)

View File

@@ -0,0 +1,24 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_prng_is_valid.c
Determine if PRNG is valid, Tom St Denis
*/
/*
Test if a PRNG index is valid
@param idx The index of the PRNG to search for
@return CRYPT_OK if valid
*/
int prng_is_valid(int idx)
{
LTC_MUTEX_LOCK(&ltc_prng_mutex);
if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) {
LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
return CRYPT_INVALID_PRNG;
}
LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
return CRYPT_OK;
}

View File

@@ -0,0 +1,7 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#ifdef LTC_PRNG_ENABLE_LTC_RNG
unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void));
#endif

View File

@@ -0,0 +1,104 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_register_all_ciphers.c
Steffen Jaeckel
*/
#define REGISTER_CIPHER(h) do {\
LTC_ARGCHK(register_cipher(h) != -1); \
} while(0)
int register_all_ciphers(void)
{
#ifdef LTC_RIJNDAEL
/* `aesni_desc` is explicitely not registered, since it's handled from within the `aes_desc` */
#ifdef ENCRYPT_ONLY
/* alternative would be
* register_cipher(&rijndael_enc_desc);
*/
REGISTER_CIPHER(&aes_enc_desc);
#else
/* alternative would be
* register_cipher(&rijndael_desc);
*/
REGISTER_CIPHER(&aes_desc);
#endif
#endif
#ifdef LTC_BLOWFISH
REGISTER_CIPHER(&blowfish_desc);
#endif
#ifdef LTC_XTEA
REGISTER_CIPHER(&xtea_desc);
#endif
#ifdef LTC_RC5
REGISTER_CIPHER(&rc5_desc);
#endif
#ifdef LTC_RC6
REGISTER_CIPHER(&rc6_desc);
#endif
#ifdef LTC_SAFERP
REGISTER_CIPHER(&saferp_desc);
#endif
#ifdef LTC_TWOFISH
REGISTER_CIPHER(&twofish_desc);
#endif
#ifdef LTC_SAFER
REGISTER_CIPHER(&safer_k64_desc);
REGISTER_CIPHER(&safer_sk64_desc);
REGISTER_CIPHER(&safer_k128_desc);
REGISTER_CIPHER(&safer_sk128_desc);
#endif
#ifdef LTC_RC2
REGISTER_CIPHER(&rc2_desc);
#endif
#ifdef LTC_DES
REGISTER_CIPHER(&des_desc);
REGISTER_CIPHER(&desx_desc);
REGISTER_CIPHER(&des3_desc);
#endif
#ifdef LTC_SM4
REGISTER_CIPHER(&sm4_desc);
#endif
#ifdef LTC_CAST5
REGISTER_CIPHER(&cast5_desc);
#endif
#ifdef LTC_NOEKEON
REGISTER_CIPHER(&noekeon_desc);
#endif
#ifdef LTC_SKIPJACK
REGISTER_CIPHER(&skipjack_desc);
#endif
#ifdef LTC_ANUBIS
REGISTER_CIPHER(&anubis_desc);
#endif
#ifdef LTC_KHAZAD
REGISTER_CIPHER(&khazad_desc);
#endif
#ifdef LTC_KSEED
REGISTER_CIPHER(&kseed_desc);
#endif
#ifdef LTC_KASUMI
REGISTER_CIPHER(&kasumi_desc);
#endif
#ifdef LTC_MULTI2
REGISTER_CIPHER(&multi2_desc);
#endif
#ifdef LTC_CAMELLIA
REGISTER_CIPHER(&camellia_desc);
#endif
#ifdef LTC_IDEA
REGISTER_CIPHER(&idea_desc);
#endif
#ifdef LTC_SERPENT
REGISTER_CIPHER(&serpent_desc);
#endif
#ifdef LTC_TEA
REGISTER_CIPHER(&tea_desc);
#endif
return CRYPT_OK;
}

View File

@@ -0,0 +1,96 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_register_all_hashes.c
Steffen Jaeckel
*/
#define REGISTER_HASH(h) do {\
LTC_ARGCHK(register_hash(h) != -1); \
} while(0)
int register_all_hashes(void)
{
#ifdef LTC_TIGER
REGISTER_HASH(&tiger_desc);
REGISTER_HASH(&tiger2_desc);
#endif
#ifdef LTC_MD2
REGISTER_HASH(&md2_desc);
#endif
#ifdef LTC_MD4
REGISTER_HASH(&md4_desc);
#endif
#ifdef LTC_MD5
REGISTER_HASH(&md5_desc);
#endif
#ifdef LTC_SHA1
REGISTER_HASH(&sha1_desc);
#endif
#ifdef LTC_SHA224
REGISTER_HASH(&sha224_desc);
#endif
#ifdef LTC_SHA256
REGISTER_HASH(&sha256_desc);
#endif
#ifdef LTC_SHA384
REGISTER_HASH(&sha384_desc);
#endif
#ifdef LTC_SHA512
REGISTER_HASH(&sha512_desc);
#endif
#ifdef LTC_SHA512_224
REGISTER_HASH(&sha512_224_desc);
#endif
#ifdef LTC_SHA512_256
REGISTER_HASH(&sha512_256_desc);
#endif
#ifdef LTC_SHA3
REGISTER_HASH(&sha3_224_desc);
REGISTER_HASH(&sha3_256_desc);
REGISTER_HASH(&sha3_384_desc);
REGISTER_HASH(&sha3_512_desc);
#endif
#ifdef LTC_KECCAK
REGISTER_HASH(&keccak_224_desc);
REGISTER_HASH(&keccak_256_desc);
REGISTER_HASH(&keccak_384_desc);
REGISTER_HASH(&keccak_512_desc);
#endif
#ifdef LTC_RIPEMD128
REGISTER_HASH(&rmd128_desc);
#endif
#ifdef LTC_RIPEMD160
REGISTER_HASH(&rmd160_desc);
#endif
#ifdef LTC_RIPEMD256
REGISTER_HASH(&rmd256_desc);
#endif
#ifdef LTC_RIPEMD320
REGISTER_HASH(&rmd320_desc);
#endif
#ifdef LTC_WHIRLPOOL
REGISTER_HASH(&whirlpool_desc);
#endif
#ifdef LTC_BLAKE2S
REGISTER_HASH(&blake2s_128_desc);
REGISTER_HASH(&blake2s_160_desc);
REGISTER_HASH(&blake2s_224_desc);
REGISTER_HASH(&blake2s_256_desc);
#endif
#ifdef LTC_BLAKE2S
REGISTER_HASH(&blake2b_160_desc);
REGISTER_HASH(&blake2b_256_desc);
REGISTER_HASH(&blake2b_384_desc);
REGISTER_HASH(&blake2b_512_desc);
#endif
#ifdef LTC_CHC_HASH
REGISTER_HASH(&chc_desc);
LTC_ARGCHK(chc_register(find_cipher_any("aes", 8, 16)) == CRYPT_OK);
#endif
return CRYPT_OK;
}

View File

@@ -0,0 +1,38 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_register_all_prngs.c
Steffen Jaeckel
*/
#define REGISTER_PRNG(h) do {\
LTC_ARGCHK(register_prng(h) != -1); \
} while(0)
int register_all_prngs(void)
{
#ifdef LTC_YARROW
REGISTER_PRNG(&yarrow_desc);
#endif
#ifdef LTC_FORTUNA
REGISTER_PRNG(&fortuna_desc);
#endif
#ifdef LTC_RC4
REGISTER_PRNG(&rc4_desc);
#endif
#ifdef LTC_CHACHA20_PRNG
REGISTER_PRNG(&chacha20_prng_desc);
#endif
#ifdef LTC_SOBER128
REGISTER_PRNG(&sober128_desc);
#endif
#ifdef LTC_SPRNG
REGISTER_PRNG(&sprng_desc);
#endif
return CRYPT_OK;
}

View File

@@ -0,0 +1,42 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_register_cipher.c
Register a cipher, Tom St Denis
*/
/**
Register a cipher with the descriptor table
@param cipher The cipher you wish to register
@return value >= 0 if successfully added (or already present), -1 if unsuccessful
*/
int register_cipher(const struct ltc_cipher_descriptor *cipher)
{
int x;
LTC_ARGCHK(cipher != NULL);
/* is it already registered? */
LTC_MUTEX_LOCK(&ltc_cipher_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) {
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return x;
}
}
/* find a blank spot */
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name == NULL) {
XMEMCPY(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor));
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return x;
}
}
/* no spot */
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return -1;
}

View File

@@ -0,0 +1,42 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_register_hash.c
Register a HASH, Tom St Denis
*/
/**
Register a hash with the descriptor table
@param hash The hash you wish to register
@return value >= 0 if successfully added (or already present), -1 if unsuccessful
*/
int register_hash(const struct ltc_hash_descriptor *hash)
{
int x;
LTC_ARGCHK(hash != NULL);
/* is it already registered? */
LTC_MUTEX_LOCK(&ltc_hash_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return x;
}
}
/* find a blank spot */
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].name == NULL) {
XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor));
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return x;
}
}
/* no spot */
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return -1;
}

View File

@@ -0,0 +1,42 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_register_prng.c
Register a PRNG, Tom St Denis
*/
/**
Register a PRNG with the descriptor table
@param prng The PRNG you wish to register
@return value >= 0 if successfully added (or already present), -1 if unsuccessful
*/
int register_prng(const struct ltc_prng_descriptor *prng)
{
int x;
LTC_ARGCHK(prng != NULL);
/* is it already registered? */
LTC_MUTEX_LOCK(&ltc_prng_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) {
LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
return x;
}
}
/* find a blank spot */
for (x = 0; x < TAB_SIZE; x++) {
if (prng_descriptor[x].name == NULL) {
XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor));
LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
return x;
}
}
/* no spot */
LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
return -1;
}

View File

@@ -0,0 +1,354 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_sizes.c
Make various struct sizes available to dynamic languages
like Python - Larry Bugbee, February 2013
LB - Dec 2013 - revised to include compiler define options
*/
typedef struct {
const char *name;
const unsigned int size;
} crypt_size;
#define SZ_STRINGIFY_S(s) { #s, sizeof(struct s) }
#define SZ_STRINGIFY_T(s) { #s, sizeof(s) }
static const crypt_size s_crypt_sizes[] = {
/* hash state sizes */
SZ_STRINGIFY_S(ltc_hash_descriptor),
SZ_STRINGIFY_T(hash_state),
#ifdef LTC_CHC_HASH
SZ_STRINGIFY_S(chc_state),
#endif
#ifdef LTC_WHIRLPOOL
SZ_STRINGIFY_S(whirlpool_state),
#endif
#ifdef LTC_SHA3
SZ_STRINGIFY_S(sha3_state),
#endif
#ifdef LTC_SHA512
SZ_STRINGIFY_S(sha512_state),
#endif
#ifdef LTC_SHA256
SZ_STRINGIFY_S(sha256_state),
#endif
#ifdef LTC_SHA1
SZ_STRINGIFY_S(sha1_state),
#endif
#ifdef LTC_MD5
SZ_STRINGIFY_S(md5_state),
#endif
#ifdef LTC_MD4
SZ_STRINGIFY_S(md4_state),
#endif
#ifdef LTC_MD2
SZ_STRINGIFY_S(md2_state),
#endif
#ifdef LTC_TIGER
SZ_STRINGIFY_S(tiger_state),
#endif
#ifdef LTC_RIPEMD128
SZ_STRINGIFY_S(rmd128_state),
#endif
#ifdef LTC_RIPEMD160
SZ_STRINGIFY_S(rmd160_state),
#endif
#ifdef LTC_RIPEMD256
SZ_STRINGIFY_S(rmd256_state),
#endif
#ifdef LTC_RIPEMD320
SZ_STRINGIFY_S(rmd320_state),
#endif
#ifdef LTC_BLAKE2S
SZ_STRINGIFY_S(blake2s_state),
#endif
#ifdef LTC_BLAKE2B
SZ_STRINGIFY_S(blake2b_state),
#endif
/* block cipher key sizes */
SZ_STRINGIFY_S(ltc_cipher_descriptor),
SZ_STRINGIFY_T(symmetric_key),
#ifdef LTC_ANUBIS
SZ_STRINGIFY_S(anubis_key),
#endif
#ifdef LTC_CAMELLIA
SZ_STRINGIFY_S(camellia_key),
#endif
#ifdef LTC_BLOWFISH
SZ_STRINGIFY_S(blowfish_key),
#endif
#ifdef LTC_CAST5
SZ_STRINGIFY_S(cast5_key),
#endif
#ifdef LTC_DES
SZ_STRINGIFY_S(des_key),
SZ_STRINGIFY_S(des3_key),
#endif
#ifdef LTC_SM4
SZ_STRINGIFY_S(sm4_key),
#endif
#ifdef LTC_IDEA
SZ_STRINGIFY_S(idea_key),
#endif
#ifdef LTC_KASUMI
SZ_STRINGIFY_S(kasumi_key),
#endif
#ifdef LTC_KHAZAD
SZ_STRINGIFY_S(khazad_key),
#endif
#ifdef LTC_KSEED
SZ_STRINGIFY_S(kseed_key),
#endif
#ifdef LTC_MULTI2
SZ_STRINGIFY_S(multi2_key),
#endif
#ifdef LTC_NOEKEON
SZ_STRINGIFY_S(noekeon_key),
#endif
#ifdef LTC_RC2
SZ_STRINGIFY_S(rc2_key),
#endif
#ifdef LTC_RC5
SZ_STRINGIFY_S(rc5_key),
#endif
#ifdef LTC_RC6
SZ_STRINGIFY_S(rc6_key),
#endif
#ifdef LTC_SERPENT
SZ_STRINGIFY_S(serpent_key),
#endif
#ifdef LTC_SKIPJACK
SZ_STRINGIFY_S(skipjack_key),
#endif
#ifdef LTC_XTEA
SZ_STRINGIFY_S(xtea_key),
#endif
#ifdef LTC_RIJNDAEL
SZ_STRINGIFY_S(rijndael_key),
#endif
#ifdef LTC_SAFER
SZ_STRINGIFY_S(safer_key),
#endif
#ifdef LTC_SAFERP
SZ_STRINGIFY_S(saferp_key),
#endif
#ifdef LTC_TWOFISH
SZ_STRINGIFY_S(twofish_key),
#endif
/* mode sizes */
#ifdef LTC_ECB_MODE
SZ_STRINGIFY_T(symmetric_ECB),
#endif
#ifdef LTC_CFB_MODE
SZ_STRINGIFY_T(symmetric_CFB),
#endif
#ifdef LTC_OFB_MODE
SZ_STRINGIFY_T(symmetric_OFB),
#endif
#ifdef LTC_CBC_MODE
SZ_STRINGIFY_T(symmetric_CBC),
#endif
#ifdef LTC_CTR_MODE
SZ_STRINGIFY_T(symmetric_CTR),
#endif
#ifdef LTC_LRW_MODE
SZ_STRINGIFY_T(symmetric_LRW),
#endif
#ifdef LTC_F8_MODE
SZ_STRINGIFY_T(symmetric_F8),
#endif
#ifdef LTC_XTS_MODE
SZ_STRINGIFY_T(symmetric_xts),
#endif
/* stream cipher sizes */
#ifdef LTC_CHACHA
SZ_STRINGIFY_T(chacha_state),
#endif
#ifdef LTC_SALSA20
SZ_STRINGIFY_T(salsa20_state),
#endif
#ifdef LTC_SOSEMANUK
SZ_STRINGIFY_T(sosemanuk_state),
#endif
#ifdef LTC_RABBIT
SZ_STRINGIFY_T(rabbit_state),
#endif
#ifdef LTC_RC4_STREAM
SZ_STRINGIFY_T(rc4_state),
#endif
#ifdef LTC_SOBER128_STREAM
SZ_STRINGIFY_T(sober128_state),
#endif
/* MAC sizes -- no states for ccm, lrw */
#ifdef LTC_HMAC
SZ_STRINGIFY_T(hmac_state),
#endif
#ifdef LTC_OMAC
SZ_STRINGIFY_T(omac_state),
#endif
#ifdef LTC_PMAC
SZ_STRINGIFY_T(pmac_state),
#endif
#ifdef LTC_POLY1305
SZ_STRINGIFY_T(poly1305_state),
#endif
#ifdef LTC_EAX_MODE
SZ_STRINGIFY_T(eax_state),
#endif
#ifdef LTC_OCB_MODE
SZ_STRINGIFY_T(ocb_state),
#endif
#ifdef LTC_OCB3_MODE
SZ_STRINGIFY_T(ocb3_state),
#endif
#ifdef LTC_CCM_MODE
SZ_STRINGIFY_T(ccm_state),
#endif
#ifdef LTC_GCM_MODE
SZ_STRINGIFY_T(gcm_state),
#endif
#ifdef LTC_PELICAN
SZ_STRINGIFY_T(pelican_state),
#endif
#ifdef LTC_XCBC
SZ_STRINGIFY_T(xcbc_state),
#endif
#ifdef LTC_F9_MODE
SZ_STRINGIFY_T(f9_state),
#endif
#ifdef LTC_CHACHA20POLY1305_MODE
SZ_STRINGIFY_T(chacha20poly1305_state),
#endif
/* asymmetric keys */
#ifdef LTC_MRSA
SZ_STRINGIFY_T(rsa_key),
#endif
#ifdef LTC_MDSA
SZ_STRINGIFY_T(dsa_key),
#endif
#ifdef LTC_MDH
SZ_STRINGIFY_T(dh_key),
#endif
#ifdef LTC_MECC
SZ_STRINGIFY_T(ltc_ecc_curve),
SZ_STRINGIFY_T(ecc_point),
SZ_STRINGIFY_T(ecc_key),
#endif
/* DER handling */
#ifdef LTC_DER
SZ_STRINGIFY_T(ltc_asn1_list), /* a list entry */
SZ_STRINGIFY_T(ltc_utctime),
SZ_STRINGIFY_T(ltc_generalizedtime),
#endif
/* prng state sizes */
SZ_STRINGIFY_S(ltc_prng_descriptor),
SZ_STRINGIFY_T(prng_state),
#ifdef LTC_FORTUNA
SZ_STRINGIFY_S(fortuna_prng),
#endif
#ifdef LTC_CHACHA20_PRNG
SZ_STRINGIFY_S(chacha20_prng),
#endif
#ifdef LTC_RC4
SZ_STRINGIFY_S(rc4_prng),
#endif
#ifdef LTC_SOBER128
SZ_STRINGIFY_S(sober128_prng),
#endif
#ifdef LTC_YARROW
SZ_STRINGIFY_S(yarrow_prng),
#endif
/* sprng has no state as it uses other potentially available sources */
/* like /dev/random. See Developers Guide for more info. */
#ifdef LTC_ADLER32
SZ_STRINGIFY_T(adler32_state),
#endif
#ifdef LTC_CRC32
SZ_STRINGIFY_T(crc32_state),
#endif
SZ_STRINGIFY_T(ltc_mp_digit),
SZ_STRINGIFY_T(ltc_math_descriptor)
};
/* crypt_get_size()
* sizeout will be the size (bytes) of the named struct or union
* return -1 if named item not found
*/
int crypt_get_size(const char* namein, unsigned int *sizeout) {
int i;
int count = sizeof(s_crypt_sizes) / sizeof(s_crypt_sizes[0]);
for (i=0; i<count; i++) {
if (XSTRCMP(s_crypt_sizes[i].name, namein) == 0) {
*sizeout = s_crypt_sizes[i].size;
return 0;
}
}
return -1;
}
/* crypt_list_all_sizes()
* if names_list is NULL, names_list_size will be the minimum
* size needed to receive the complete names_list
* if names_list is NOT NULL, names_list must be the addr with
* sufficient memory allocated into which the names_list
* is to be written. Also, the value in names_list_size
* sets the upper bound of the number of characters to be
* written.
* a -1 return value signifies insufficient space made available
*/
int crypt_list_all_sizes(char *names_list, unsigned int *names_list_size) {
int i;
unsigned int total_len = 0;
char *ptr;
int number_len;
int count = sizeof(s_crypt_sizes) / sizeof(s_crypt_sizes[0]);
/* calculate amount of memory required for the list */
for (i=0; i<count; i++) {
number_len = snprintf(NULL, 0, "%s,%u\n", s_crypt_sizes[i].name, s_crypt_sizes[i].size);
if (number_len < 0) {
return -1;
}
total_len += number_len;
/* this last +1 is for newlines (and ending NULL) */
}
if (names_list == NULL) {
*names_list_size = total_len;
} else {
if (total_len > *names_list_size) {
return -1;
}
/* build the names list */
ptr = names_list;
for (i=0; i<count; i++) {
number_len = snprintf(ptr, total_len, "%s,%u\n", s_crypt_sizes[i].name, s_crypt_sizes[i].size);
if (number_len < 0) return -1;
if ((unsigned int)number_len > total_len) return -1;
total_len -= number_len;
ptr += number_len;
}
/* to remove the trailing new-line */
ptr -= 1;
*ptr = 0;
}
return 0;
}

View File

@@ -0,0 +1,33 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_unregister_cipher.c
Unregister a cipher, Tom St Denis
*/
/**
Unregister a cipher from the descriptor table
@param cipher The cipher descriptor to remove
@return CRYPT_OK on success
*/
int unregister_cipher(const struct ltc_cipher_descriptor *cipher)
{
int x;
LTC_ARGCHK(cipher != NULL);
/* is it already registered? */
LTC_MUTEX_LOCK(&ltc_cipher_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (XMEMCMP(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)) == 0) {
cipher_descriptor[x].name = NULL;
cipher_descriptor[x].ID = 255;
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return CRYPT_OK;
}
}
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return CRYPT_ERROR;
}

View File

@@ -0,0 +1,32 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_unregister_hash.c
Unregister a hash, Tom St Denis
*/
/**
Unregister a hash from the descriptor table
@param hash The hash descriptor to remove
@return CRYPT_OK on success
*/
int unregister_hash(const struct ltc_hash_descriptor *hash)
{
int x;
LTC_ARGCHK(hash != NULL);
/* is it already registered? */
LTC_MUTEX_LOCK(&ltc_hash_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {
hash_descriptor[x].name = NULL;
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return CRYPT_OK;
}
}
LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
return CRYPT_ERROR;
}

View File

@@ -0,0 +1,32 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file crypt_unregister_prng.c
Unregister a PRNG, Tom St Denis
*/
/**
Unregister a PRNG from the descriptor table
@param prng The PRNG descriptor to remove
@return CRYPT_OK on success
*/
int unregister_prng(const struct ltc_prng_descriptor *prng)
{
int x;
LTC_ARGCHK(prng != NULL);
/* is it already registered? */
LTC_MUTEX_LOCK(&ltc_prng_mutex);
for (x = 0; x < TAB_SIZE; x++) {
if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) {
prng_descriptor[x].name = NULL;
LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
return CRYPT_OK;
}
}
LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
return CRYPT_ERROR;
}

View File

@@ -0,0 +1,71 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file error_to_string.c
Convert error codes to ASCII strings, Tom St Denis
*/
static const char * const err_2_str[CRYPT_ERR_NUM] =
{
"CRYPT_OK",
"CRYPT_ERROR",
"Non-fatal 'no-operation' requested.",
"Invalid key size.",
"Invalid number of rounds for block cipher.",
"Algorithm failed test vectors.",
"Buffer overflow.",
"Invalid input packet.",
"Invalid number of bits for a PRNG.",
"Error reading the PRNG.",
"Invalid cipher specified.",
"Invalid hash specified.",
"Invalid PRNG specified.",
"Out of memory.",
"Invalid PK key or key type specified for function.",
"A private PK key is required.",
"Invalid argument provided.",
"File Not Found",
"Invalid PK type.",
"An overflow of a value was detected/prevented.",
"An ASN.1 decoding error occurred.",
"The input was longer than expected.",
"Invalid size input for PK parameters.",
"Invalid size for prime.",
"Invalid padding.",
"Hash applied to too many bits.",
"Password context to decrypt key file is missing.",
"The PEM header was not recognized",
};
LTC_STATIC_ASSERT(correct_err_2_str_size, (sizeof(err_2_str)/sizeof(err_2_str[0])) == CRYPT_ERR_NUM)
/**
Convert an LTC error code to ASCII
@param err The error code
@return A pointer to the ASCII NUL terminated string for the error or "Invalid error code." if the err code was not valid.
*/
const char *error_to_string(int err)
{
if (err < 0 || err >= CRYPT_ERR_NUM) {
return "Invalid error code.";
}
return err_2_str[err];
}

View File

@@ -0,0 +1,135 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "tomcrypt_private.h"
#ifdef LTC_HKDF
/* This is mostly just a wrapper around hmac_memory */
int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
/* libtomcrypt chokes on a zero length HMAC key, so we need to check for
that. HMAC specifies that keys shorter than the hash's blocksize are
0 padded to the block size. HKDF specifies that a NULL salt is to be
substituted with a salt comprised of hashLen 0 bytes. HMAC's padding
means that in either case the HMAC is actually using a blocksize long
zero filled key. Unless blocksize < hashLen (which wouldn't make any
sense), we can use a single 0 byte as the HMAC key and still generate
valid results for HKDF. */
if (salt == NULL || saltlen == 0) {
return hmac_memory(hash_idx, (const unsigned char *)"", 1, in, inlen, out, outlen);
}
return hmac_memory(hash_idx, salt, saltlen, in, inlen, out, outlen);
}
int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long outlen)
{
unsigned long hashsize;
int err;
unsigned char N;
unsigned long Noutlen, outoff;
unsigned char *T, *dat;
unsigned long Tlen, datlen;
/* make sure hash descriptor is valid */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
return err;
}
hashsize = hash_descriptor[hash_idx].hashsize;
/* RFC5869 parameter restrictions */
if (inlen < hashsize || outlen > hashsize * 255) {
return CRYPT_INVALID_ARG;
}
if (info == NULL && infolen != 0) {
return CRYPT_INVALID_ARG;
}
LTC_ARGCHK(out != NULL);
Tlen = hashsize + infolen + 1;
T = XMALLOC(Tlen); /* Replace with static buffer? */
if (T == NULL) {
return CRYPT_MEM;
}
if (info != NULL) {
XMEMCPY(T + hashsize, info, infolen);
}
/* HMAC data T(1) doesn't include a previous hash value */
dat = T + hashsize;
datlen = Tlen - hashsize;
N = 0;
outoff = 0; /* offset in out to write to */
while (1) { /* an exit condition breaks mid-loop */
Noutlen = MIN(hashsize, outlen - outoff);
T[Tlen - 1] = ++N;
if ((err = hmac_memory(hash_idx, in, inlen, dat, datlen,
out + outoff, &Noutlen)) != CRYPT_OK) {
zeromem(T, Tlen);
XFREE(T);
return err;
}
outoff += Noutlen;
if (outoff >= outlen) { /* loop exit condition */
break;
}
/* All subsequent HMAC data T(N) DOES include the previous hash value */
XMEMCPY(T, out + hashsize * (N-1), hashsize);
if (N == 1) {
dat = T;
datlen = Tlen;
}
}
zeromem(T, Tlen);
XFREE(T);
return CRYPT_OK;
}
/* all in one step */
int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen,
const unsigned char *info, unsigned long infolen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long outlen)
{
unsigned long hashsize;
int err;
unsigned char *extracted;
/* make sure hash descriptor is valid */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
return err;
}
hashsize = hash_descriptor[hash_idx].hashsize;
extracted = XMALLOC(hashsize); /* replace with static buffer? */
if (extracted == NULL) {
return CRYPT_MEM;
}
if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) {
zeromem(extracted, hashsize);
XFREE(extracted);
return err;
}
err = hkdf_expand(hash_idx, info, infolen, extracted, hashsize, out, outlen);
zeromem(extracted, hashsize);
XFREE(extracted);
return err;
}
#endif /* LTC_HKDF */
/* vim: set ts=2 sw=2 et ai si: */

View File

@@ -0,0 +1,284 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file hkdf_test.c
LTC_HKDF support, self-test, Steffen Jaeckel
*/
#ifdef LTC_HKDF
/*
TEST CASES SOURCE:
Internet Engineering Task Force (IETF) H. Krawczyk
Request for Comments: 5869 IBM Research
Category: Informational P. Eronen
ISSN: 2070-1721 Nokia
May 2010
Appendix A. Test Vectors
*/
/**
LTC_HKDF self-test
@return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled.
*/
int hkdf_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
unsigned char OKM[82];
int i;
static const struct hkdf_test_case {
int num;
const char* Hash;
unsigned char IKM[80];
unsigned long IKM_l;
unsigned char salt[80];
unsigned long salt_l;
unsigned char info[80];
unsigned long info_l;
unsigned char PRK[32];
unsigned long PRK_l;
unsigned char OKM[82];
unsigned long OKM_l;
} cases[] = {
#ifdef LTC_SHA256
/*
Basic test case with SHA-256
Hash = SHA-256
IKM = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets)
salt = 0x000102030405060708090a0b0c (13 octets)
info = 0xf0f1f2f3f4f5f6f7f8f9 (10 octets)
L = 42
PRK = 0x077709362c2e32df0ddc3f0dc47bba63
90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets)
OKM = 0x3cb25f25faacd57a90434f64d0362f2a
2d2d0a90cf1a5a4c5db02d56ecc4c5bf
34007208d5b887185865 (42 octets)
*/
{1, "sha256",
{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22,
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13,
{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9}, 10,
{0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf,
0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63,
0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31,
0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}, 32,
{0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
0x58, 0x65}, 42},
#ifdef LTC_TEST_EXT
/* Test with SHA-256 and longer inputs/outputs */
{2, "sha256",
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80,
{0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80,
{0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80,
{0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a,
0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c,
0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01,
0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44}, 32,
{0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1,
0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72,
0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
0x1d, 0x87}, 82},
/* Test with SHA-256 and zero length salt/info */
{3, "sha256",
{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22,
{0}, 0,
{0}, 0,
{0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16,
0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf,
0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77,
0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}, 32,
{0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f,
0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a,
0x96, 0xc8}, 42},
#endif /* LTC_TEST_EXT */
#endif /* LTC_SHA256 */
#ifdef LTC_SHA1
/* Basic test case with SHA-1 */
{4, "sha1",
{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b}, 11,
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13,
{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9}, 10,
{0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f,
0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b,
0xaa, 0x2b, 0xa2, 0x43}, 20,
{0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69,
0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81,
0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2,
0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3,
0xf8, 0x96}, 42},
#ifdef LTC_TEST_EXT
/* Test with SHA-1 and longer inputs/outputs */
{5, "sha1",
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80,
{0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80,
{0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80,
{0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59,
0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a,
0x22, 0x4c, 0xfa, 0xf6}, 20,
{0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7,
0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb,
0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe,
0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3,
0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c,
0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed,
0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e,
0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43,
0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52,
0xd3, 0xb4}, 82},
/* Test with SHA-1 and zero-length salt/info */
{6, "sha1",
{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22,
{0}, 0,
{0}, 0,
{0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28,
0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a,
0xa0, 0xd3, 0x2d, 0x01}, 20,
{0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61,
0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06,
0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0,
0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3,
0x49, 0x18}, 42},
/* Test with SHA-1, salt not provided (defaults to HashLen zero octets),
zero-length info */
{7, "sha1",
{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 22,
{0}, 0, /* pass a null pointer */
{0}, 0,
{0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c,
0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e,
0x73, 0x13, 0x85, 0xdd}, 20,
{0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3,
0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a,
0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5,
0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac,
0xfc, 0x48}, 42},
#endif /* LTC_TEST_EXT */
#endif /* LTC_SHA1 */
};
int err;
int tested=0,failed=0;
for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
int hash = find_hash(cases[i].Hash);
if (hash == -1) continue;
++tested;
if((err = hkdf(hash, cases[i].salt, cases[i].salt_l,
cases[i].info, cases[i].info_l,
cases[i].IKM, cases[i].IKM_l,
OKM, cases[i].OKM_l)) != CRYPT_OK) {
#if defined(LTC_TEST_DBG) && (LTC_TEST_DBG > 1)
printf("LTC_HKDF-%s test #%d, %s\n", cases[i].Hash, i, error_to_string(err));
#endif
return err;
}
if(compare_testvector(OKM, cases[i].OKM_l, cases[i].OKM, (size_t)cases[i].OKM_l, "HKDF", cases[i].num)) {
failed++;
}
}
if (failed != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
if (tested == 0) {
return CRYPT_NOP;
}
return CRYPT_OK;
#endif
}
#endif

View File

@@ -0,0 +1,53 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file mem_neq.c
Compare two blocks of memory for inequality in constant time.
Steffen Jaeckel
*/
/**
Compare two blocks of memory for inequality in constant time.
The usage is similar to that of standard memcmp, but you can only test
if the memory is equal or not - you can not determine by how much the
first different byte differs.
This function shall be used to compare results of cryptographic
operations where inequality means most likely usage of a wrong key.
The execution time has therefore to be constant as otherwise
timing attacks could be possible.
@param a The first memory region
@param b The second memory region
@param len The length of the area to compare (octets)
@return 0 when a and b are equal for len bytes, 1 they are not equal.
*/
int mem_neq(const void *a, const void *b, size_t len)
{
unsigned char ret = 0;
const unsigned char* pa;
const unsigned char* pb;
LTC_ARGCHK(a != NULL);
LTC_ARGCHK(b != NULL);
pa = a;
pb = b;
while (len-- > 0) {
ret |= *pa ^ *pb;
++pa;
++pb;
}
ret |= ret >> 4;
ret |= ret >> 2;
ret |= ret >> 1;
ret &= 1;
return ret;
}

View File

@@ -0,0 +1,90 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#ifdef LTC_PADDING
/**
Remove padding from your data
This depads your data.
@param data The data to depad
@param length [in/out] The size of the data before/after (removing padding)
@param mode One of the LTC_PAD_xx flags
@return CRYPT_OK on success
*/
int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode)
{
unsigned long padded_length, unpadded_length, n;
unsigned char pad;
enum padding_type type;
LTC_ARGCHK(data != NULL);
LTC_ARGCHK(length != NULL);
padded_length = *length;
type = mode & LTC_PAD_MASK;
if (type < LTC_PAD_ONE_AND_ZERO) {
pad = data[padded_length - 1];
if (pad > padded_length || pad == 0) return CRYPT_INVALID_ARG;
unpadded_length = padded_length - pad;
} else {
/* init pad to calm old compilers */
pad = 0x0;
unpadded_length = padded_length;
}
switch (type) {
case LTC_PAD_ANSI_X923:
pad = 0x0;
/* FALLTHROUGH */
case LTC_PAD_PKCS7:
for (n = unpadded_length; n < padded_length - 1; ++n) {
if (data[n] != pad) return CRYPT_INVALID_PACKET;
}
break;
#ifdef LTC_RNG_GET_BYTES
case LTC_PAD_ISO_10126:
/* nop */
break;
#endif
case LTC_PAD_SSH:
pad = 0x1;
for (n = unpadded_length; n < padded_length; ++n) {
if (data[n] != pad++) return CRYPT_INVALID_PACKET;
}
break;
case LTC_PAD_ONE_AND_ZERO:
while (unpadded_length > 0 && data[unpadded_length - 1] != 0x80) {
if (data[unpadded_length - 1] != 0x0) return CRYPT_INVALID_PACKET;
unpadded_length--;
}
if (unpadded_length == 0) return CRYPT_INVALID_PACKET;
unpadded_length--;
if (data[unpadded_length] != 0x80) return CRYPT_INVALID_PACKET;
break;
case LTC_PAD_ZERO:
case LTC_PAD_ZERO_ALWAYS:
while (unpadded_length > 0 && data[unpadded_length - 1] == 0x0) {
unpadded_length--;
}
if (type == LTC_PAD_ZERO_ALWAYS) {
if (unpadded_length == padded_length) return CRYPT_INVALID_PACKET;
if (data[unpadded_length] != 0x0) return CRYPT_INVALID_PACKET;
}
break;
default:
return CRYPT_INVALID_ARG;
}
*length = unpadded_length;
return CRYPT_OK;
}
#endif

View File

@@ -0,0 +1,151 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#ifdef LTC_PADDING
/**
Determine the to-be-padded length.
@param length [in/out] The size of the data before/after padding
@param mode Mask of (LTC_PAD_xxx | block_length)
@return CRYPT_OK on success
*/
static int s_padding_padded_length(unsigned long *length, unsigned long mode)
{
enum padding_type padding;
unsigned char pad, block_length, r, t;
LTC_ARGCHK(length != NULL);
block_length = mode & 0xff;
padding = mode & LTC_PAD_MASK;
r = *length % block_length;
switch (padding) {
case LTC_PAD_ZERO:
if (r == 0) {
t = 0;
break;
}
/* FALLTHROUGH */
case LTC_PAD_PKCS7:
case LTC_PAD_ONE_AND_ZERO:
case LTC_PAD_ZERO_ALWAYS:
case LTC_PAD_SSH:
t = 1;
break;
#ifdef LTC_RNG_GET_BYTES
case LTC_PAD_ISO_10126:
do {
if (rng_get_bytes(&t, sizeof(t), NULL) != sizeof(t)) {
return CRYPT_ERROR_READPRNG;
}
t %= (256 / block_length);
} while (t == 0);
break;
#endif
case LTC_PAD_ANSI_X923:
if (block_length != 16) {
return CRYPT_INVALID_ARG;
}
t = 1;
break;
default:
return CRYPT_INVALID_ARG;
}
pad = (t * block_length) - r;
if ((pad == 0) && (padding != LTC_PAD_ZERO)) {
pad = block_length;
}
*length += pad;
return CRYPT_OK;
}
/**
Add padding to data.
This pads your data.
@param data The data to depad
@param length The size of the data before padding
@param padded_length [in/out] The size of the data available/after padding
@param mode One of the LTC_PAD_xx flags
@return CRYPT_OK on success
*/
int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode)
{
unsigned long l, n;
enum padding_type type;
int err;
unsigned char diff, pad;
LTC_ARGCHK(data != NULL);
LTC_ARGCHK(padded_length != NULL);
l = length;
if ((err = s_padding_padded_length(&l, mode)) != CRYPT_OK) {
return err;
}
type = mode & LTC_PAD_MASK;
if (*padded_length < l) {
#ifdef LTC_RNG_GET_BYTES
if (type != LTC_PAD_ISO_10126) {
*padded_length = l;
} else {
*padded_length = length + 256;
}
#else
*padded_length = l;
#endif
return CRYPT_BUFFER_OVERFLOW;
}
if (l - length > 255) return CRYPT_INVALID_ARG;
diff = (unsigned char)(l - length);
switch (type) {
case LTC_PAD_PKCS7:
XMEMSET(&data[length], diff, diff);
break;
#ifdef LTC_RNG_GET_BYTES
case LTC_PAD_ISO_10126:
if (rng_get_bytes(&data[length], diff-1u, NULL) != diff-1u) {
return CRYPT_ERROR_READPRNG;
}
data[l-1] = diff;
break;
#endif
case LTC_PAD_ANSI_X923:
XMEMSET(&data[length], 0, diff-1);
data[l-1] = diff;
break;
case LTC_PAD_SSH:
pad = 0x1;
for (n = length; n < l; ++n) {
data[n] = pad++;
}
break;
case LTC_PAD_ONE_AND_ZERO:
XMEMSET(&data[length + 1], 0, diff);
data[length] = 0x80;
break;
case LTC_PAD_ZERO:
case LTC_PAD_ZERO_ALWAYS:
XMEMSET(&data[length], 0, diff);
break;
default:
return CRYPT_INVALID_ARG;
}
*padded_length = l;
return CRYPT_OK;
}
#endif

View File

@@ -0,0 +1,28 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file password_free.c
Free the password inside a `struct password`, Steffen Jaeckel
*/
/**
Free a password
@param pw The password to be free'd
@param ctx The password context
*/
void password_free(struct password *pw, const struct password_ctx *ctx)
{
if (!ctx || !pw || !pw->pw)
return;
zeromem(pw->pw, pw->l);
if (ctx->free) {
ctx->free(pw->pw);
} else {
XFREE(pw->pw);
}
pw->pw = NULL;
pw->l = 0;
}

View File

@@ -0,0 +1,79 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
#ifdef LTC_PBES
/**
Decrypt Data encrypted via either PBES1 or PBES2
@param arg The according PBES parameters
@param dec_data [out] The decrypted data
@param dec_size [in/out] The length of the encrypted resp. decrypted data
@return CRYPT_OK on success
*/
int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size)
{
int err, hid, cid;
unsigned char k[32], *iv;
unsigned long klen, keylen, dlen;
long diff;
symmetric_CBC cbc;
LTC_ARGCHK(arg != NULL);
LTC_ARGCHK(arg->type.kdf != NULL);
LTC_ARGCHK(dec_data != NULL);
LTC_ARGCHK(dec_size != NULL);
hid = find_hash(arg->type.h);
if (hid == -1) return CRYPT_INVALID_HASH;
cid = find_cipher(arg->type.c);
if (cid == -1) return CRYPT_INVALID_CIPHER;
klen = arg->type.keylen;
/* RC2 special case */
if (arg->key_bits != 0) {
/* We can't handle odd lengths of Key Bits */
if ((arg->key_bits % 8) != 0) return CRYPT_INVALID_KEYSIZE;
/* Internally we use bytes, not bits */
klen = arg->key_bits / 8;
}
keylen = klen;
if (arg->iv != NULL) {
iv = arg->iv->data;
} else {
iv = k + klen;
klen += arg->type.blocklen;
}
if (klen > sizeof(k)) return CRYPT_INVALID_ARG;
if ((err = arg->type.kdf(&arg->pw, arg->salt->data, arg->salt->size, arg->iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
if ((err = cbc_start(cid, iv, k, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
if ((err = cbc_decrypt(arg->enc_data->data, dec_data, arg->enc_data->size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
dlen = arg->enc_data->size;
if ((err = padding_depad(dec_data, &dlen, LTC_PAD_PKCS7)) != CRYPT_OK) goto LBL_ERROR;
diff = (long)arg->enc_data->size - (long)dlen;
if ((diff <= 0) || (diff > cipher_descriptor[cid].block_length)) {
err = CRYPT_PK_INVALID_PADDING;
goto LBL_ERROR;
}
*dec_size = dlen;
return CRYPT_OK;
LBL_ERROR:
zeromem(k, sizeof(k));
zeromem(dec_data, *dec_size);
return err;
}
#endif
#pragma clang diagnostic pop

View File

@@ -0,0 +1,112 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#ifdef LTC_PBES
static int s_pkcs_5_alg1_wrap(const struct password *pwd,
const unsigned char *salt, unsigned long salt_len,
int iteration_count, int hash_idx,
unsigned char *out, unsigned long *outlen)
{
LTC_UNUSED_PARAM(salt_len);
return pkcs_5_alg1(pwd->pw, pwd->l, salt, iteration_count, hash_idx, out, outlen);
}
static int s_pkcs_12_wrap(const struct password *pwd,
const unsigned char *salt, unsigned long salt_len,
int iteration_count, int hash_idx,
unsigned char *out, unsigned long *outlen)
{
int err;
/* convert password to unicode/utf16-be */
unsigned long pwlen = pwd->l * 2;
unsigned char* pw;
if (*outlen < 32) return CRYPT_INVALID_ARG;
pw = XMALLOC(pwlen + 2);
if (pw == NULL) return CRYPT_MEM;
if ((err = pkcs12_utf8_to_utf16(pwd->pw, pwd->l, pw, &pwlen)) != CRYPT_OK) goto LBL_ERROR;
pw[pwlen++] = 0;
pw[pwlen++] = 0;
/* derive KEY */
if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 1, out, 24)) != CRYPT_OK) goto LBL_ERROR;
/* derive IV */
if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 2, out+24, 8)) != CRYPT_OK) goto LBL_ERROR;
*outlen = 32;
LBL_ERROR:
zeromem(pw, pwlen);
XFREE(pw);
return err;
}
static const pbes_properties s_pbes1_types[] = {
{ s_pkcs_5_alg1_wrap, "md2", "des", 8, 8 },
{ s_pkcs_5_alg1_wrap, "md2", "rc2", 8, 8 },
{ s_pkcs_5_alg1_wrap, "md5", "des", 8, 8 },
{ s_pkcs_5_alg1_wrap, "md5", "rc2", 8, 8 },
{ s_pkcs_5_alg1_wrap, "sha1", "des", 8, 8 },
{ s_pkcs_5_alg1_wrap, "sha1", "rc2", 8, 8 },
{ s_pkcs_12_wrap, "sha1", "3des", 24, 8 },
};
static const oid_to_pbes s_pbes1_list[] = {
{ &s_pbes1_types[0], "1.2.840.113549.1.5.1" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */
{ &s_pbes1_types[1], "1.2.840.113549.1.5.4" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */
{ &s_pbes1_types[2], "1.2.840.113549.1.5.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */
{ &s_pbes1_types[3], "1.2.840.113549.1.5.6" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */
{ &s_pbes1_types[4], "1.2.840.113549.1.5.10" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */
{ &s_pbes1_types[5], "1.2.840.113549.1.5.11" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */
{ &s_pbes1_types[6], "1.2.840.113549.1.12.1.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */
{ 0 },
};
static int s_pbes1_from_oid(const ltc_asn1_list *oid, pbes_properties *res)
{
unsigned int i;
for (i = 0; s_pbes1_list[i].data != NULL; ++i) {
if (pk_oid_cmp_with_asn1(s_pbes1_list[i].oid, oid) == CRYPT_OK) {
if (res != NULL) *res = *s_pbes1_list[i].data;
return CRYPT_OK;
}
}
return CRYPT_INVALID_ARG;
}
/**
Extract PBES1 parameters
@param s The start of the sequence with potential PBES1 parameters
@param res Pointer to where the extracted parameters should be stored
@return CRYPT_OK on success
*/
int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res)
{
int err;
LTC_ARGCHK(s != NULL);
LTC_ARGCHK(res != NULL);
if ((err = s_pbes1_from_oid(s, &res->type)) != CRYPT_OK) return err;
if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_OCTET_STRING) ||
!LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_INTEGER)) {
return CRYPT_INVALID_PACKET;
}
/* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC:
* 0:d=0 hl=4 l= 329 cons: SEQUENCE
* 4:d=1 hl=2 l= 27 cons: SEQUENCE
* 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3) (== *s)
* 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam)
* 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt)
* 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations)
* 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
*/
res->salt = s->next->child;
res->iterations = ltc_mp_get_int(s->next->child->next->data);
return CRYPT_OK;
}
#endif

View File

@@ -0,0 +1,201 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#ifdef LTC_PBES
static const char * const s_oid_pbes2 = "1.2.840.113549.1.5.13";
static const char * const s_oid_pbkdf2 = "1.2.840.113549.1.5.12";
typedef struct {
const char *oid;
const char *id;
} oid_id_st;
static const oid_id_st s_hmac_oid_names[] = {
{ "1.2.840.113549.2.7", "sha1" },
{ "1.2.840.113549.2.8", "sha224" },
{ "1.2.840.113549.2.9", "sha256" },
{ "1.2.840.113549.2.10", "sha384" },
{ "1.2.840.113549.2.11", "sha512" },
{ "1.2.840.113549.2.12", "sha512-224" },
{ "1.2.840.113549.2.13", "sha512-256" },
};
static int s_pkcs_5_alg2_wrap(const struct password *pwd,
const unsigned char *salt, unsigned long salt_len,
int iteration_count, int hash_idx,
unsigned char *out, unsigned long *outlen)
{
return pkcs_5_alg2(pwd->pw, pwd->l, salt, salt_len, iteration_count, hash_idx, out, outlen);
}
static const pbes_properties s_pbes2_default_types[] = {
{ s_pkcs_5_alg2_wrap, "sha1", "des", 8, 0 },
{ s_pkcs_5_alg2_wrap, "sha1", "rc2", 4, 0 },
{ s_pkcs_5_alg2_wrap, "sha1", "3des", 24, 0 },
{ s_pkcs_5_alg2_wrap, "sha1", "aes", 16, 0 },
{ s_pkcs_5_alg2_wrap, "sha1", "aes", 24, 0 },
{ s_pkcs_5_alg2_wrap, "sha1", "aes", 32, 0 },
};
static const oid_to_pbes s_pbes2_list[] = {
{ &s_pbes2_default_types[0], "1.3.14.3.2.7" }, /* http://www.oid-info.com/get/1.3.14.3.2.7 desCBC */
{ &s_pbes2_default_types[1], "1.2.840.113549.3.2" }, /* http://www.oid-info.com/get/1.2.840.113549.3.2 rc2CBC */
{ &s_pbes2_default_types[2], "1.2.840.113549.3.7" }, /* http://www.oid-info.com/get/1.2.840.113549.3.7 des-EDE3-CBC */
{ &s_pbes2_default_types[3], "2.16.840.1.101.3.4.1.2" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2 aes128-CBC */
{ &s_pbes2_default_types[4], "2.16.840.1.101.3.4.1.22" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22 aes192-CBC */
{ &s_pbes2_default_types[5], "2.16.840.1.101.3.4.1.42" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42 aes256-CBC */
};
static int s_pbes2_from_oid(const ltc_asn1_list *cipher_oid, const ltc_asn1_list *hmac_oid, pbes_properties *res)
{
unsigned int i;
for (i = 0; i < sizeof(s_pbes2_list)/sizeof(s_pbes2_list[0]); ++i) {
if (pk_oid_cmp_with_asn1(s_pbes2_list[i].oid, cipher_oid) == CRYPT_OK) {
*res = *s_pbes2_list[i].data;
break;
}
}
if (res->c == NULL) return CRYPT_INVALID_CIPHER;
if (hmac_oid != NULL) {
for (i = 0; i < sizeof(s_hmac_oid_names)/sizeof(s_hmac_oid_names[0]); ++i) {
if (pk_oid_cmp_with_asn1(s_hmac_oid_names[i].oid, hmac_oid) == CRYPT_OK) {
res->h = s_hmac_oid_names[i].id;
return CRYPT_OK;
}
}
return CRYPT_INVALID_HASH;
}
return CRYPT_OK;
}
/**
Extract PBES2 parameters
@param s The start of the sequence with potential PBES2 parameters
@param res Pointer to where the extracted parameters should be stored
@return CRYPT_OK on success
*/
int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res)
{
unsigned long klen;
ltc_asn1_list *lkdf, *lenc, *loptseq, *liter, *lhmac;
int err;
LTC_ARGCHK(s != NULL);
LTC_ARGCHK(res != NULL);
if ((err = pk_oid_cmp_with_asn1(s_oid_pbes2, s)) != CRYPT_OK) return err;
if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(s->next->child->child, LTC_ASN1_OBJECT_IDENTIFIER) ||
!LTC_ASN1_IS_TYPE(s->next->child->child->next, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(s->next->child->next->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
return CRYPT_INVALID_PACKET;
}
/* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc:
* 0:d=0 hl=4 l= 380 cons: SEQUENCE
* 4:d=1 hl=2 l= 78 cons: SEQUENCE
* 6:d=2 hl=2 l= 9 prim: OBJECT :PBES2 (== 1.2.840.113549.1.5.13) (== *s)
* 17:d=2 hl=2 l= 65 cons: SEQUENCE
* 19:d=3 hl=2 l= 41 cons: SEQUENCE
* 21:d=4 hl=2 l= 9 prim: OBJECT :PBKDF2 (== *lkdf)
* 32:d=4 hl=2 l= 28 cons: SEQUENCE
* 34:d=5 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== res->salt)
* 44:d=5 hl=2 l= 2 prim: INTEGER :0800 (== res->iterations, *liter)
* 48:d=5 hl=2 l= 12 cons: SEQUENCE (== *loptseq - this sequence is optional, may be missing)
* 50:d=6 hl=2 l= 8 prim: OBJECT :hmacWithSHA256 (== *lhmac)
* 60:d=6 hl=2 l= 0 prim: NULL
* 62:d=3 hl=2 l= 20 cons: SEQUENCE
* 64:d=4 hl=2 l= 8 prim: OBJECT :des-ede3-cbc (== *lenc)
* 74:d=4 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:B1404C4688DC9A5A
* 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
*/
lkdf = s->next->child->child;
lenc = s->next->child->next->child;
if ((err = pk_oid_cmp_with_asn1(s_oid_pbkdf2, lkdf)) != CRYPT_OK) return err;
if (!LTC_ASN1_IS_TYPE(lkdf->next, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(lkdf->next->child, LTC_ASN1_OCTET_STRING) ||
!LTC_ASN1_IS_TYPE(lkdf->next->child->next, LTC_ASN1_INTEGER)) {
return CRYPT_INVALID_PACKET;
}
liter = lkdf->next->child->next;
loptseq = liter->next;
res->salt = lkdf->next->child;
res->iterations = ltc_mp_get_int(liter->data);
/* There's an optional INTEGER keyLength after the iterations, skip that if it's there.
* c.f. RFC 2898 A.2 PBKDF2 */
if(LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_INTEGER)) {
loptseq = loptseq->next;
}
/* this sequence is optional */
lhmac = NULL;
if (LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_SEQUENCE) &&
LTC_ASN1_IS_TYPE(loptseq->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
lhmac = loptseq->child;
}
if ((err = s_pbes2_from_oid(lenc, lhmac, &res->type)) != CRYPT_OK) return err;
if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_OCTET_STRING)) {
/* 'NON-RC2'-CBC */
res->iv = lenc->next;
} else if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_SEQUENCE)) {
/* RC2-CBC is a bit special ...
*
* RC2-CBC-Parameter ::= SEQUENCE {
* rc2ParameterVersion INTEGER OPTIONAL,
* iv OCTET STRING (SIZE(8)) }
*/
if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_INTEGER) &&
LTC_ASN1_IS_TYPE(lenc->next->child->next, LTC_ASN1_OCTET_STRING)) {
klen = ltc_mp_get_int(lenc->next->child->data);
res->iv = lenc->next->child->next;
/*
* Effective Key Bits Encoding
* 40 160
* 64 120
* 128 58
* b >= 256 b
*/
switch (klen) {
case 160:
res->key_bits = 40;
break;
case 120:
res->key_bits = 64;
break;
case 58:
res->key_bits = 128;
break;
default:
/* We don't handle undefined Key Bits */
if (klen < 256) return CRYPT_INVALID_KEYSIZE;
res->key_bits = klen;
break;
}
} else if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_OCTET_STRING)) {
res->iv = lenc->next->child;
/*
* If the rc2ParameterVersion field is omitted, the "effective key bits"
* defaults to 32.
*/
res->key_bits = 32;
} else {
return CRYPT_INVALID_PACKET;
}
}
return CRYPT_OK;
}
#endif

View File

@@ -0,0 +1,344 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
/**
@file pem.c
Const declarations for PEM, Steffen Jaeckel
*/
#ifdef LTC_PEM
const struct pem_header_id pem_std_headers[] = {
{
/* PKCS#8 encrypted */
SET_CSTR(.start, "-----BEGIN ENCRYPTED PRIVATE KEY-----"),
SET_CSTR(.end, "-----END ENCRYPTED PRIVATE KEY-----"),
.has_more_headers = no,
.flags = pf_encrypted_pkcs8,
},
{
/* PKCS#8 plain */
SET_CSTR(.start, "-----BEGIN PRIVATE KEY-----"),
SET_CSTR(.end, "-----END PRIVATE KEY-----"),
.has_more_headers = no,
.flags = pf_pkcs8,
},
{
/* X.509 Certificates */
SET_CSTR(.start, "-----BEGIN CERTIFICATE-----"),
SET_CSTR(.end, "-----END CERTIFICATE-----"),
.has_more_headers = no,
.flags = pf_x509,
},
{
/* Regular (plain) public keys */
SET_CSTR(.start, "-----BEGIN PUBLIC KEY-----"),
SET_CSTR(.end, "-----END PUBLIC KEY-----"),
.has_more_headers = no,
.flags = pf_public,
},
{
SET_CSTR(.start, "-----BEGIN RSA PUBLIC KEY-----"),
SET_CSTR(.end, "-----END RSA PUBLIC KEY-----"),
.has_more_headers = no,
.pka = LTC_PKA_RSA,
.flags = pf_public,
},
/* Regular plain or encrypted private keys */
{
SET_CSTR(.start, "-----BEGIN RSA PRIVATE KEY-----"),
SET_CSTR(.end, "-----END RSA PRIVATE KEY-----"),
.has_more_headers = maybe,
.pka = LTC_PKA_RSA,
},
{
SET_CSTR(.start, "-----BEGIN EC PRIVATE KEY-----"),
SET_CSTR(.end, "-----END EC PRIVATE KEY-----"),
.has_more_headers = maybe,
.pka = LTC_PKA_EC,
},
{
SET_CSTR(.start, "-----BEGIN DSA PRIVATE KEY-----"),
SET_CSTR(.end, "-----END DSA PRIVATE KEY-----"),
.has_more_headers = maybe,
.pka = LTC_PKA_DSA,
},
};
const unsigned long pem_std_headers_num = sizeof(pem_std_headers)/sizeof(pem_std_headers[0]);
/* Encrypted PEM files */
const struct str pem_proc_type_encrypted = { SET_CSTR(, "Proc-Type: 4,ENCRYPTED") };
#if defined(LTC_SSH)
const struct str pem_ssh_comment = { SET_CSTR(, "Comment: ") };
#endif
const struct str pem_dek_info_start = { SET_CSTR(, "DEK-Info: ") };
const struct blockcipher_info pem_dek_infos[] =
{
{ .name = "AES-128-CBC,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cbc, },
{ .name = "AES-192-CBC,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cbc, },
{ .name = "AES-256-CBC,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cbc, },
{ .name = "AES-128-CFB,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cfb, },
{ .name = "AES-192-CFB,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cfb, },
{ .name = "AES-256-CFB,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cfb, },
{ .name = "AES-128-CFB1,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cfb1, },
{ .name = "AES-192-CFB1,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cfb1, },
{ .name = "AES-256-CFB1,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cfb1, },
{ .name = "AES-128-CFB8,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cfb8, },
{ .name = "AES-192-CFB8,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cfb8, },
{ .name = "AES-256-CFB8,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cfb8, },
{ .name = "AES-128-CTR,", .algo = "aes", .keylen = 128 / 8, .mode = cm_ctr, },
{ .name = "AES-192-CTR,", .algo = "aes", .keylen = 192 / 8, .mode = cm_ctr, },
{ .name = "AES-256-CTR,", .algo = "aes", .keylen = 256 / 8, .mode = cm_ctr, },
{ .name = "AES-128-OFB,", .algo = "aes", .keylen = 128 / 8, .mode = cm_ofb, },
{ .name = "AES-192-OFB,", .algo = "aes", .keylen = 192 / 8, .mode = cm_ofb, },
{ .name = "AES-256-OFB,", .algo = "aes", .keylen = 256 / 8, .mode = cm_ofb, },
{ .name = "BF-CBC,", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_cbc, },
{ .name = "BF-CFB,", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_cfb, },
{ .name = "BF-OFB,", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_ofb, },
{ .name = "CAMELLIA-128-CBC,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cbc, },
{ .name = "CAMELLIA-192-CBC,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cbc, },
{ .name = "CAMELLIA-256-CBC,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cbc, },
{ .name = "CAMELLIA-128-CFB,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cfb, },
{ .name = "CAMELLIA-192-CFB,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cfb, },
{ .name = "CAMELLIA-256-CFB,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cfb, },
{ .name = "CAMELLIA-128-CFB1,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cfb1, },
{ .name = "CAMELLIA-192-CFB1,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cfb1, },
{ .name = "CAMELLIA-256-CFB1,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cfb1, },
{ .name = "CAMELLIA-128-CFB8,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cfb8, },
{ .name = "CAMELLIA-192-CFB8,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cfb8, },
{ .name = "CAMELLIA-256-CFB8,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cfb8, },
{ .name = "CAMELLIA-128-CTR,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_ctr, },
{ .name = "CAMELLIA-192-CTR,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_ctr, },
{ .name = "CAMELLIA-256-CTR,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_ctr, },
{ .name = "CAMELLIA-128-OFB,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_ofb, },
{ .name = "CAMELLIA-192-OFB,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_ofb, },
{ .name = "CAMELLIA-256-OFB,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_ofb, },
{ .name = "CAST5-CBC,", .algo = "cast5", .keylen = 128 / 8, .mode = cm_cbc, },
{ .name = "CAST5-CFB,", .algo = "cast5", .keylen = 128 / 8, .mode = cm_cfb, },
{ .name = "CAST5-OFB,", .algo = "cast5", .keylen = 128 / 8, .mode = cm_ofb, },
{ .name = "ChaCha20,", .algo = "chacha20", .keylen = 256 / 8, .mode = cm_stream, },
{ .name = "DES-EDE-CBC,", .algo = "3des", .keylen = 128 / 8, .mode = cm_cbc, },
{ .name = "DES-EDE-CFB,", .algo = "3des", .keylen = 128 / 8, .mode = cm_cfb, },
{ .name = "DES-EDE-OFB,", .algo = "3des", .keylen = 128 / 8, .mode = cm_ofb, },
{ .name = "DES-EDE3-CBC,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cbc, },
{ .name = "DES-EDE3-CFB,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cfb, },
{ .name = "DES-EDE3-CFB1,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cfb1, },
{ .name = "DES-EDE3-CFB8,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cfb8, },
{ .name = "DES-EDE3-OFB,", .algo = "3des", .keylen = 192 / 8, .mode = cm_ofb, },
{ .name = "DES-CBC,", .algo = "des", .keylen = 64 / 8, .mode = cm_cbc, },
{ .name = "DES-CFB,", .algo = "des", .keylen = 64 / 8, .mode = cm_cfb, },
{ .name = "DES-CFB1,", .algo = "des", .keylen = 64 / 8, .mode = cm_cfb1, },
{ .name = "DES-CFB8,", .algo = "des", .keylen = 64 / 8, .mode = cm_cfb8, },
{ .name = "DES-OFB,", .algo = "des", .keylen = 64 / 8, .mode = cm_ofb, },
{ .name = "DESX-CBC,", .algo = "desx", .keylen = 192 / 8, .mode = cm_cbc, },
{ .name = "IDEA-CBC,", .algo = "idea", .keylen = 128 / 8, .mode = cm_cbc, },
{ .name = "IDEA-CFB,", .algo = "idea", .keylen = 128 / 8, .mode = cm_cfb, },
{ .name = "IDEA-OFB,", .algo = "idea", .keylen = 128 / 8, .mode = cm_ofb, },
{ .name = "RC5-CBC,", .algo = "rc5", .keylen = 128 / 8, .mode = cm_cbc, },
{ .name = "RC5-CFB,", .algo = "rc5", .keylen = 128 / 8, .mode = cm_cfb, },
{ .name = "RC5-OFB,", .algo = "rc5", .keylen = 128 / 8, .mode = cm_ofb, },
{ .name = "RC2-40-CBC,", .algo = "rc2", .keylen = 40 / 8, .mode = cm_cbc, },
{ .name = "RC2-64-CBC,", .algo = "rc2", .keylen = 64 / 8, .mode = cm_cbc, },
{ .name = "RC2-CBC,", .algo = "rc2", .keylen = 128 / 8, .mode = cm_cbc, },
{ .name = "RC2-CFB,", .algo = "rc2", .keylen = 128 / 8, .mode = cm_cfb, },
{ .name = "RC2-OFB,", .algo = "rc2", .keylen = 128 / 8, .mode = cm_ofb, },
{ .name = "SEED-CBC,", .algo = "seed", .keylen = 128 / 8, .mode = cm_cbc, },
{ .name = "SEED-CFB,", .algo = "seed", .keylen = 128 / 8, .mode = cm_cfb, },
{ .name = "SEED-OFB,", .algo = "seed", .keylen = 128 / 8, .mode = cm_ofb, },
};
const unsigned long pem_dek_infos_num = sizeof(pem_dek_infos)/sizeof(pem_dek_infos[0]);
int pem_decrypt(unsigned char *data, unsigned long *datalen,
unsigned char *key, unsigned long keylen,
unsigned char *iv, unsigned long ivlen,
unsigned char *tag, unsigned long taglen,
const struct blockcipher_info *info,
enum padding_type padding)
{
int err, cipher = -1;
struct {
union {
#ifdef LTC_CBC_MODE
symmetric_CBC cbc;
#endif
#ifdef LTC_CFB_MODE
symmetric_CFB cfb;
#endif
#ifdef LTC_CTR_MODE
symmetric_CTR ctr;
#endif
#ifdef LTC_OFB_MODE
symmetric_OFB ofb;
#endif
} ctx;
} s;
enum cipher_mode mode = info->mode & cm_modes;
if (mode != cm_stream) {
cipher = find_cipher(info->algo);
if (cipher == -1) {
return CRYPT_INVALID_CIPHER;
}
}
switch (info->mode) {
case cm_cbc:
#ifdef LTC_CBC_MODE
LTC_ARGCHK(ivlen == (unsigned long)cipher_descriptor[cipher].block_length);
if ((err = cbc_start(cipher, iv, key, keylen, 0, &s.ctx.cbc)) != CRYPT_OK) {
goto error_out;
}
if ((err = cbc_decrypt(data, data, *datalen, &s.ctx.cbc)) != CRYPT_OK) {
goto error_out;
}
if ((err = cbc_done(&s.ctx.cbc)) != CRYPT_OK) {
goto error_out;
}
if ((err = padding_depad(data, datalen, padding | s.ctx.cbc.blocklen)) != CRYPT_OK) {
goto error_out;
}
#else
return CRYPT_INVALID_CIPHER;
#endif
break;
case cm_cfb:
case cm_cfb1:
case cm_cfb8:
#ifdef LTC_CFB_MODE
if (info->mode == cm_cfb) {
if ((err = cfb_start(cipher, iv, key, keylen, 0, &s.ctx.cfb)) != CRYPT_OK) {
goto error_out;
}
} else {
if ((err = cfb_start_ex(cipher, iv, key, keylen, 0, info->mode == cm_cfb1 ? 1 : 8, &s.ctx.cfb)) != CRYPT_OK) {
goto error_out;
}
}
if ((err = cfb_decrypt(data, data, *datalen, &s.ctx.cfb)) != CRYPT_OK) {
goto error_out;
}
if ((err = cfb_done(&s.ctx.cfb)) != CRYPT_OK) {
goto error_out;
}
#else
return CRYPT_INVALID_CIPHER;
#endif
break;
case cm_ctr:
#ifdef LTC_CTR_MODE
if ((err = ctr_start(cipher, iv, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN, &s.ctx.ctr)) != CRYPT_OK) {
goto error_out;
}
if ((err = ctr_decrypt(data, data, *datalen, &s.ctx.ctr)) != CRYPT_OK) {
goto error_out;
}
if ((err = ctr_done(&s.ctx.ctr)) != CRYPT_OK) {
goto error_out;
}
#else
return CRYPT_INVALID_CIPHER;
#endif
break;
case cm_ofb:
#ifdef LTC_OFB_MODE
if ((err = ofb_start(cipher, iv, key, keylen, 0, &s.ctx.ofb)) != CRYPT_OK) {
goto error_out;
}
if ((err = ofb_decrypt(data, data, *datalen, &s.ctx.ofb)) != CRYPT_OK) {
goto error_out;
}
if ((err = ofb_done(&s.ctx.ofb)) != CRYPT_OK) {
goto error_out;
}
#else
return CRYPT_INVALID_CIPHER;
#endif
break;
case cm_gcm:
#ifdef LTC_GCM_MODE
if ((err = gcm_memory(cipher,
key, keylen,
iv, ivlen,
NULL, 0,
data, *datalen, data,
tag, &taglen,
GCM_DECRYPT)) != CRYPT_OK) {
goto error_out;
}
#else
LTC_UNUSED_PARAM(tag);
LTC_UNUSED_PARAM(taglen);
return CRYPT_INVALID_CIPHER;
#endif
break;
case cm_stream:
#ifdef LTC_CHACHA
LTC_ARGCHK(ivlen == 16);
if ((err = chacha_memory(key, keylen, 20,
iv, ivlen, 0,
data, *datalen, data)) != CRYPT_OK) {
goto error_out;
}
#else
return CRYPT_INVALID_CIPHER;
#endif
break;
case cm_stream_openssh:
#ifdef LTC_CHACHA20POLY1305_MODE
if ((err = chacha20poly1305_memory(key, 32,
iv, ivlen,
NULL, 0,
data, *datalen, data,
tag, &taglen,
CHACHA20POLY1305_DECRYPT | CHACHA20POLY1305_OPENSSH_COMPAT)) != CRYPT_OK) {
goto error_out;
}
#else
return CRYPT_INVALID_CIPHER;
#endif
break;
default:
err = CRYPT_INVALID_ARG;
break;
}
error_out:
return err;
}
#ifndef LTC_NO_FILE
int pem_decode_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx)
{
int err = pem_decode_pkcs_filehandle(f, k, pw_ctx);
if (err == CRYPT_OK || err != CRYPT_UNKNOWN_PEM)
return err;
#if defined(LTC_SSH)
rewind(f);
err = pem_decode_openssh_filehandle(f, k, pw_ctx);
#endif
return err;
}
#endif
int pem_decode(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx)
{
int err = pem_decode_pkcs(buf, len, k, pw_ctx);
if (err == CRYPT_OK || err != CRYPT_UNKNOWN_PEM)
return err;
#if defined(LTC_SSH)
err = pem_decode_openssh(buf, len, k, pw_ctx);
#endif
return err;
}
#endif /* LTC_PEM */
#pragma clang diagnostic pop

View File

@@ -0,0 +1,298 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
/**
@file pem_decode.c
Decode a PEM file, Steffen Jaeckel
*/
#ifdef LTC_PEM
extern const struct pem_header_id pem_std_headers[];
extern const unsigned long pem_std_headers_num;
static int s_decrypt_pem(unsigned char *pem, unsigned long *l, const struct pem_headers *hdr)
{
unsigned char iv[MAXBLOCKSIZE], key[MAXBLOCKSIZE];
unsigned long ivlen, klen;
int err;
if (hdr->info.keylen > sizeof(key)) {
return CRYPT_BUFFER_OVERFLOW;
}
if (!hdr->pw->pw) {
return CRYPT_INVALID_ARG;
}
ivlen = sizeof(iv);
if ((err = base16_decode(hdr->info.iv, XSTRLEN(hdr->info.iv), iv, &ivlen)) != CRYPT_OK) {
return err;
}
klen = hdr->info.keylen;
if ((err = pkcs_5_alg1_openssl(hdr->pw->pw, hdr->pw->l, iv, 1, find_hash("md5"), key, &klen))) {
return err;
}
err = pem_decrypt(pem, l, key, klen, iv, ivlen, NULL, 0, &hdr->info, LTC_PAD_PKCS7);
zeromem(key, sizeof(key));
zeromem(iv, sizeof(iv));
return err;
}
static int s_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka)
{
der_flexi_check flexi_should[4];
ltc_asn1_list *seqid, *id;
enum ltc_oid_id oid_id;
int err;
unsigned long n = 0;
LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seqid);
LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_BIT_STRING, NULL);
LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL);
if ((err = der_flexi_sequence_cmp(pub, flexi_should)) != CRYPT_OK) {
return err;
}
n = 0;
LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OBJECT_IDENTIFIER, &id);
LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL);
err = der_flexi_sequence_cmp(seqid, flexi_should);
if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
return err;
}
if ((err = pk_get_oid_from_asn1(id, &oid_id)) != CRYPT_OK) {
return err;
}
return pk_get_pka_id(oid_id, pka);
}
typedef int (*import_fn)(const unsigned char *, unsigned long, void*);
static const import_fn s_import_x509_fns[LTC_PKA_NUM] = {
#ifdef LTC_MRSA
[LTC_PKA_RSA] = (import_fn)rsa_import_x509,
#endif
#ifdef LTC_MECC
[LTC_PKA_EC] = (import_fn)ecc_import_x509,
#endif
#ifdef LTC_CURVE25519
[LTC_PKA_X25519] = (import_fn)x25519_import_x509,
[LTC_PKA_ED25519] = (import_fn)ed25519_import_x509,
#endif
};
static int s_import_x509(unsigned char *pem, unsigned long l, ltc_pka_key *k)
{
enum ltc_pka_id pka = LTC_PKA_UNDEF;
ltc_asn1_list *d, *spki;
int err;
if ((err = x509_decode_spki(pem, l, &d, &spki)) != CRYPT_OK) {
return err;
}
err = s_get_pka(spki, &pka);
der_free_sequence_flexi(d);
if (err != CRYPT_OK) {
return err;
}
if (pka < 0
|| pka > sizeof(s_import_x509_fns)/sizeof(s_import_x509_fns[0])
|| s_import_x509_fns[pka] == NULL) {
return CRYPT_PK_INVALID_TYPE;
}
if ((err = s_import_x509_fns[pka](pem, l, &k->u)) == CRYPT_OK) {
k->id = pka;
}
return err;
}
static int s_import_pkcs8(unsigned char *pem, unsigned long l, ltc_pka_key *k, const password_ctx *pw_ctx)
{
int err;
enum ltc_oid_id pka;
ltc_asn1_list *alg_id, *priv_key;
ltc_asn1_list *p8_asn1 = NULL;
if ((err = pkcs8_decode_flexi(pem, l, pw_ctx, &p8_asn1)) != CRYPT_OK) {
goto cleanup;
}
if ((err = pkcs8_get_children(p8_asn1, &pka, &alg_id, &priv_key)) != CRYPT_OK) {
goto cleanup;
}
switch (pka) {
#ifdef LTC_MDH
case LTC_OID_DH:
err = dh_import_pkcs8_asn1(alg_id, priv_key, &k->u.dh);
k->id = LTC_PKA_DH;
break;
#endif
#ifdef LTC_MDSA
case LTC_OID_DSA:
err = dsa_import_pkcs8_asn1(alg_id, priv_key, &k->u.dsa);
k->id = LTC_PKA_DSA;
break;
#endif
#ifdef LTC_MRSA
case LTC_OID_RSA:
err = rsa_import_pkcs8_asn1(alg_id, priv_key, &k->u.rsa);
k->id = LTC_PKA_RSA;
break;
#endif
#ifdef LTC_MECC
case LTC_OID_EC:
err = ecc_import_pkcs8_asn1(alg_id, priv_key, &k->u.ecc);
k->id = LTC_PKA_EC;
break;
#endif
#ifdef LTC_CURVE25519
case LTC_OID_X25519:
err = x25519_import_pkcs8_asn1(alg_id, priv_key, &k->u.x25519);
k->id = LTC_PKA_X25519;
break;
case LTC_OID_ED25519:
err = ed25519_import_pkcs8_asn1(alg_id, priv_key, &k->u.ed25519);
k->id = LTC_PKA_ED25519;
break;
#endif
default:
err = CRYPT_PK_INVALID_TYPE;
}
cleanup:
if (p8_asn1) {
der_sequence_free(p8_asn1);
}
return err;
}
static int s_extract_pka(unsigned char *pem, unsigned long w, enum ltc_pka_id *pka)
{
ltc_asn1_list *pub;
int err = CRYPT_ERROR;
if ((err = der_decode_sequence_flexi(pem, &w, &pub)) != CRYPT_OK) {
return err;
}
err = s_get_pka(pub, pka);
der_sequence_free(pub);
return err;
}
static const import_fn s_import_openssl_fns[LTC_PKA_NUM] = {
#ifdef LTC_MRSA
[LTC_PKA_RSA] = (import_fn)rsa_import,
#endif
#ifdef LTC_MDSA
[LTC_PKA_DSA] = (import_fn)dsa_import,
#endif
#ifdef LTC_MECC
[LTC_PKA_EC] = (import_fn)ecc_import_openssl,
#endif
#ifdef LTC_CURVE25519
[LTC_PKA_X25519] = (import_fn)x25519_import,
[LTC_PKA_ED25519] = (import_fn)ed25519_import,
#endif
};
static int s_decode(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_ctx)
{
unsigned char *pem = NULL;
unsigned long w, l, n;
int err = CRYPT_ERROR;
struct pem_headers hdr = { 0 };
struct password pw = { 0 };
enum ltc_pka_id pka;
XMEMSET(k, 0, sizeof(*k));
w = LTC_PEM_READ_BUFSIZE * 2;
retry:
pem = XREALLOC(pem, w);
for (n = 0; n < pem_std_headers_num; ++n) {
hdr.id = &pem_std_headers[n];
err = pem_read(pem, &w, &hdr, g);
if (err == CRYPT_BUFFER_OVERFLOW) {
goto retry;
} else if (err == CRYPT_OK) {
break;
} else if (err != CRYPT_UNKNOWN_PEM) {
goto cleanup;
}
hdr.id = NULL;
}
/* id not found */
if (hdr.id == NULL)
goto cleanup;
l = w;
if (hdr.id->flags & pf_pkcs8) {
err = s_import_pkcs8(pem, l, k, pw_ctx);
goto cleanup;
} else if (hdr.id->flags == pf_x509) {
err = s_import_x509(pem, l, k);
goto cleanup;
} else if ((hdr.id->flags & pf_public) && hdr.id->pka == LTC_PKA_UNDEF) {
if ((err = s_extract_pka(pem, w, &pka)) != CRYPT_OK) {
goto cleanup;
}
} else if (hdr.encrypted) {
if ((pw_ctx == NULL) || (pw_ctx->callback == NULL)) {
err = CRYPT_PW_CTX_MISSING;
goto cleanup;
}
hdr.pw = &pw;
if (pw_ctx->callback(&hdr.pw->pw, &hdr.pw->l, pw_ctx->userdata)) {
err = CRYPT_ERROR;
goto cleanup;
}
if ((err = s_decrypt_pem(pem, &l, &hdr)) != CRYPT_OK) {
goto cleanup;
}
pka = hdr.id->pka;
} else {
pka = hdr.id->pka;
}
if (pka < 0
|| pka > sizeof(s_import_openssl_fns)/sizeof(s_import_openssl_fns[0])
|| s_import_openssl_fns[pka] == NULL) {
err = CRYPT_PK_INVALID_TYPE;
goto cleanup;
}
if ((err = s_import_openssl_fns[pka](pem, l, &k->u)) == CRYPT_OK) {
k->id = pka;
}
cleanup:
password_free(hdr.pw, pw_ctx);
XFREE(pem);
return err;
}
#ifndef LTC_NO_FILE
int pem_decode_pkcs_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx)
{
LTC_ARGCHK(f != NULL);
LTC_ARGCHK(k != NULL);
{
struct get_char g = { .get = pem_get_char_from_file, .data.f = f };
return s_decode(&g, k, pw_ctx);
}
}
#endif /* LTC_NO_FILE */
int pem_decode_pkcs(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx)
{
LTC_ARGCHK(buf != NULL);
LTC_ARGCHK(len != 0);
LTC_ARGCHK(k != NULL);
{
struct get_char g = { .get = pem_get_char_from_buf, SET_BUFP(.data.buf, buf, len) };
return s_decode(&g, k, pw_ctx);
}
}
#endif /* LTC_PEM */
#pragma clang diagnostic pop

View File

@@ -0,0 +1,244 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file pem_read.c
Read and interpret a PEM file, Steffen Jaeckel
*/
#ifdef LTC_PEM
extern const struct str pem_proc_type_encrypted;
#ifdef LTC_SSH
extern const struct str pem_ssh_comment;
#endif
extern const struct str pem_dek_info_start;
extern const struct blockcipher_info pem_dek_infos[];
extern const unsigned long pem_dek_infos_num;
#ifndef LTC_NO_FILE
int pem_get_char_from_file(struct get_char *g)
{
return getc(g->data.f);
}
#endif /* LTC_NO_FILE */
int pem_get_char_from_buf(struct get_char *g)
{
int ret;
if (g->data.buf.work == g->data.buf.end) {
return -1;
}
ret = *g->data.buf.work;
g->data.buf.work++;
return ret;
}
static void s_unget_line(char *buf, unsigned long buflen, struct get_char *g)
{
if (buflen > sizeof(g->unget_buf_))
return;
g->unget_buf.p = g->unget_buf_;
COPY_STR(g->unget_buf, buf, buflen);
}
static void s_tts(char *buf, unsigned long *buflen)
{
while(1) {
unsigned long blen = *buflen;
if (blen < 2)
return;
blen--;
switch (buf[blen]) {
case ' ':
case '\t':
buf[blen] = '\0';
*buflen = blen;
break;
default:
return;
}
}
}
static char* s_get_line(char *buf, unsigned long *buflen, struct get_char *g)
{
unsigned long blen = 0;
int c = -1, c_;
if (g->unget_buf.p) {
if (*buflen < g->unget_buf.len) {
return NULL;
}
XMEMCPY(buf, g->unget_buf.p, g->unget_buf.len);
*buflen = g->unget_buf.len;
RESET_STR(g->unget_buf);
return buf;
}
while(blen < *buflen) {
c_ = c;
c = g->get(g);
if (c == '\n') {
buf[blen] = '\0';
if (c_ == '\r') {
buf[--blen] = '\0';
}
s_tts(buf, &blen);
*buflen = blen;
return buf;
}
if (c == -1 || c == '\0') {
buf[blen] = '\0';
s_tts(buf, &blen);
*buflen = blen;
return buf;
}
buf[blen] = c;
blen++;
}
return NULL;
}
static LTC_INLINE int s_fits_buf(void *dest, unsigned long to_write, void *end)
{
unsigned char *d = dest;
unsigned char *e = end;
unsigned char *w = d + to_write;
if (w < d || w > e)
return 0;
return 1;
}
static int s_pem_decode_headers(struct pem_headers *hdr, struct get_char *g)
{
char buf[LTC_PEM_DECODE_BUFSZ], *alg_start;
unsigned long slen, tmplen, n;
int has_more_headers = hdr->id->has_more_headers == no ? 0 : 3;
/* Make sure the PEM has the appropriate extension headers if required.
*
* ```
* Proc-Type: 4,ENCRYPTED[\r]\n
* DEK-Info: <algorithm>,<IV>[\r]\n
* [\r]\n
* ```
*/
while (has_more_headers) {
slen = sizeof(buf);
if (!s_get_line(buf, &slen, g) || (has_more_headers > 1 && slen == 0)) {
return CRYPT_INVALID_PACKET;
}
switch (has_more_headers) {
case 3:
if (XMEMCMP(buf, pem_proc_type_encrypted.p, pem_proc_type_encrypted.len)) {
#ifdef LTC_SSH
if (XMEMCMP(buf, pem_ssh_comment.p, pem_ssh_comment.len))
#endif
s_unget_line(buf, slen, g);
if (hdr->id->has_more_headers == maybe)
return CRYPT_OK;
else
return CRYPT_INVALID_PACKET;
}
hdr->encrypted = 1;
break;
case 2:
hdr->info.algo = NULL;
if (XMEMCMP(buf, pem_dek_info_start.p, pem_dek_info_start.len))
return CRYPT_INVALID_PACKET;
alg_start = &buf[pem_dek_info_start.len];
for (n = 0; n < pem_dek_infos_num; ++n) {
unsigned long namelen = XSTRLEN(pem_dek_infos[n].name);
if (slen >= namelen + pem_dek_info_start.len && !XMEMCMP(alg_start, pem_dek_infos[n].name, namelen)) {
char *iv = alg_start + namelen;
hdr->info = pem_dek_infos[n];
tmplen = XSTRLEN(iv);
if (tmplen > sizeof(hdr->info.iv))
return CRYPT_INVALID_KEYSIZE;
XMEMCPY(hdr->info.iv, iv, tmplen);
break;
}
}
if (hdr->info.algo == NULL) {
return CRYPT_INVALID_CIPHER;
}
break;
case 1:
/* Make sure that there's an empty line in between */
if (buf[0] != '\0')
return CRYPT_INVALID_PACKET;
break;
default:
return CRYPT_INVALID_CIPHER;
}
has_more_headers--;
}
return CRYPT_OK;
}
int pem_read(void *pem, unsigned long *w, struct pem_headers *hdr, struct get_char *g)
{
char buf[LTC_PEM_DECODE_BUFSZ];
char *wpem = pem;
char *end = wpem + *w;
unsigned long slen, linelen;
int err, hdr_ok = 0;
int would_overflow = 0;
unsigned char empty_lines = 0;
linelen = sizeof(buf);
if (s_get_line(buf, &linelen, g) == NULL) {
return CRYPT_INVALID_PACKET;
}
if (hdr->id->start.len != linelen || XMEMCMP(buf, hdr->id->start.p, hdr->id->start.len)) {
s_unget_line(buf, linelen, g);
return CRYPT_UNKNOWN_PEM;
}
hdr->encrypted = hdr->id->flags & pf_encrypted;
if ((err = s_pem_decode_headers(hdr, g)) != CRYPT_OK)
return err;
/* Read the base64 encoded part of the PEM */
slen = sizeof(buf);
while (s_get_line(buf, &slen, g)) {
if (slen == hdr->id->end.len && !XMEMCMP(buf, hdr->id->end.p, slen)) {
hdr_ok = 1;
break;
}
if (!slen) {
if (empty_lines)
break;
empty_lines++;
}
if (!would_overflow && s_fits_buf(wpem, slen, end)) {
XMEMCPY(wpem, buf, slen);
} else {
would_overflow = 1;
}
wpem += slen;
slen = sizeof(buf);
}
if (!hdr_ok)
return CRYPT_INVALID_PACKET;
if (would_overflow || !s_fits_buf(wpem, 1, end)) {
/* NUL termination */
wpem++;
/* prevent a wrap-around */
if (wpem < (char*)pem)
return CRYPT_OVERFLOW;
*w = wpem - (char*)pem;
return CRYPT_BUFFER_OVERFLOW;
}
*w = wpem - (char*)pem;
*wpem++ = '\0';
if ((err = base64_strict_decode(pem, *w, pem, w)) != CRYPT_OK) {
return err;
}
return CRYPT_OK;
}
#endif /* LTC_PEM */

View File

@@ -0,0 +1,861 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
/**
@file pem_ssh.c
SSH specific functionality to process PEM files, Steffen Jaeckel
The basic format of the key is described here:
https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
*/
#if defined(LTC_PEM_SSH)
/* Table as of
* https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-17
*/
const struct blockcipher_info ssh_ciphers[] =
{
{ .name = "none", .algo = "", .keylen = 0, .mode = cm_none },
{ .name = "aes128-cbc", .algo = "aes", .keylen = 128 / 8, .mode = cm_cbc },
{ .name = "aes128-ctr", .algo = "aes", .keylen = 128 / 8, .mode = cm_ctr },
{ .name = "aes192-cbc", .algo = "aes", .keylen = 192 / 8, .mode = cm_cbc },
{ .name = "aes192-ctr", .algo = "aes", .keylen = 192 / 8, .mode = cm_ctr },
{ .name = "aes256-cbc", .algo = "aes", .keylen = 256 / 8, .mode = cm_cbc },
{ .name = "aes256-ctr", .algo = "aes", .keylen = 256 / 8, .mode = cm_ctr },
{ .name = "aes128-gcm@openssh.com", .algo = "aes", .keylen = 128 / 8, .mode = cm_gcm },
{ .name = "aes256-gcm@openssh.com", .algo = "aes", .keylen = 256 / 8, .mode = cm_gcm },
{ .name = "blowfish128-cbc", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_cbc },
{ .name = "blowfish128-ctr", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_ctr },
/* The algo name doesn't matter, it's only used in pem-info */
{ .name = "chacha20-poly1305@openssh.com", .algo = "c20p1305", .keylen = 256 / 8, .mode = cm_stream | cm_openssh },
{ .name = "des-cbc", .algo = "des", .keylen = 64 / 8, .mode = cm_cbc },
{ .name = "3des-cbc", .algo = "3des", .keylen = 192 / 8, .mode = cm_cbc },
{ .name = "3des-ctr", .algo = "3des", .keylen = 192 / 8, .mode = cm_ctr },
{ .name = "serpent128-cbc", .algo = "serpent", .keylen = 128 / 8, .mode = cm_cbc },
{ .name = "serpent128-ctr", .algo = "serpent", .keylen = 128 / 8, .mode = cm_ctr },
{ .name = "serpent192-cbc", .algo = "serpent", .keylen = 192 / 8, .mode = cm_cbc },
{ .name = "serpent192-ctr", .algo = "serpent", .keylen = 192 / 8, .mode = cm_ctr },
{ .name = "serpent256-cbc", .algo = "serpent", .keylen = 256 / 8, .mode = cm_cbc },
{ .name = "serpent256-ctr", .algo = "serpent", .keylen = 256 / 8, .mode = cm_ctr },
{ .name = "twofish128-cbc", .algo = "twofish", .keylen = 128 / 8, .mode = cm_cbc },
{ .name = "twofish128-ctr", .algo = "twofish", .keylen = 128 / 8, .mode = cm_ctr },
{ .name = "twofish192-cbc", .algo = "twofish", .keylen = 192 / 8, .mode = cm_cbc },
{ .name = "twofish192-ctr", .algo = "twofish", .keylen = 192 / 8, .mode = cm_ctr },
{ .name = "twofish-cbc", .algo = "twofish", .keylen = 256 / 8, .mode = cm_cbc },
{ .name = "twofish256-cbc", .algo = "twofish", .keylen = 256 / 8, .mode = cm_cbc },
{ .name = "twofish256-ctr", .algo = "twofish", .keylen = 256 / 8, .mode = cm_ctr },
};
const unsigned long ssh_ciphers_num = sizeof(ssh_ciphers)/sizeof(ssh_ciphers[0]);
struct kdf_options {
const char *name;
const struct blockcipher_info *cipher;
unsigned char salt[64];
unsigned long saltlen;
ulong32 num_rounds;
struct password pw;
};
#ifdef LTC_MECC
static int s_ssh_find_ecc(const char *pka, const ltc_ecc_curve **curve)
{
int err;
const char* prefix = "ecdsa-sha2-";
unsigned long prefixlen = XSTRLEN(prefix);
if (strstr(pka, prefix) == NULL) return CRYPT_PK_INVALID_TYPE;
if ((err = ecc_find_curve(pka + prefixlen, curve)) != CRYPT_OK) return err;
return CRYPT_OK;
}
static int s_ssh_find_init_ecc(const char *pka, ltc_pka_key *key)
{
int err;
const ltc_ecc_curve *cu;
if ((err = s_ssh_find_ecc(pka, &cu)) != CRYPT_OK) return err;
return ecc_set_curve(cu, &key->u.ecc);
}
static int s_ssh_decode_ecdsa(const unsigned char *in, unsigned long *inlen, ltc_pka_key *pka_key, enum pem_flags type)
{
int err;
unsigned char groupname[64], buf0[512], buf1[512];
unsigned long groupnamelen = sizeof(groupname), buf0len = sizeof(buf0), buf1len = sizeof(buf1);
unsigned long remaining, cur_len, keylen;
const unsigned char *p, *key;
p = in;
cur_len = *inlen;
remaining = *inlen;
err = ssh_decode_sequence_multi(p, &cur_len,
LTC_SSHDATA_STRING, groupname, &groupnamelen,
LTC_SSHDATA_STRING, buf0, &buf0len,
LTC_SSHDATA_STRING, buf1, &buf1len,
LTC_SSHDATA_EOL, LTC_NULL);
if (err == CRYPT_OK) {
key = buf1;
keylen = buf1len;
} else if (err == CRYPT_BUFFER_OVERFLOW && buf0len != sizeof(buf0) && buf1len == sizeof(buf1)) {
key = buf0;
keylen = buf0len;
} else {
goto cleanup;
}
remaining -= cur_len;
cur_len = remaining;
err = ecc_set_key(key, keylen, type == pf_public ? PK_PUBLIC : PK_PRIVATE, &pka_key->u.ecc);
cleanup:
zeromem(groupname, sizeof(groupname));
zeromem(buf0, sizeof(buf0));
zeromem(buf1, sizeof(buf1));
if (err == CRYPT_OK) {
pka_key->id = LTC_PKA_EC;
*inlen -= remaining;
}
return err;
}
#endif
#ifdef LTC_CURVE25519
static int s_ssh_decode_ed25519(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, enum pem_flags type)
{
int err;
unsigned char pubkey[64], privkey[96];
unsigned long pubkeylen = sizeof(pubkey), privkeylen = sizeof(privkey);
unsigned long remaining, cur_len;
const unsigned char *p;
p = in;
cur_len = *inlen;
remaining = *inlen;
if ((err = ssh_decode_sequence_multi(p, &cur_len,
LTC_SSHDATA_STRING, pubkey, &pubkeylen,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
goto cleanup;
}
if (type == pf_public) {
if ((err = ed25519_import_raw(pubkey, pubkeylen, PK_PUBLIC, &key->u.ed25519)) != CRYPT_OK) {
goto cleanup;
}
key->id = LTC_PKA_ED25519;
goto cleanup;
}
p += cur_len;
remaining -= cur_len;
cur_len = remaining;
if ((err = ssh_decode_sequence_multi(p, &cur_len,
LTC_SSHDATA_STRING, privkey, &privkeylen,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
goto cleanup;
}
if ((err = ed25519_import_raw(privkey, privkeylen, PK_PRIVATE, &key->u.ed25519)) != CRYPT_OK) {
goto cleanup;
}
key->id = LTC_PKA_ED25519;
cleanup:
zeromem(pubkey, sizeof(pubkey));
zeromem(privkey, sizeof(privkey));
if (err == CRYPT_OK) {
remaining -= cur_len;
*inlen -= remaining;
}
return err;
}
#endif
#ifdef LTC_MRSA
static int s_ssh_decode_dsa(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, enum pem_flags type)
{
int err, stat;
unsigned long remaining, cur_len;
const unsigned char *p;
if ((err = dsa_int_init(&key->u.dsa)) != CRYPT_OK) {
return err;
}
p = in;
cur_len = *inlen;
remaining = *inlen;
if ((err = ssh_decode_sequence_multi(p, &cur_len,
LTC_SSHDATA_MPINT, key->u.dsa.p,
LTC_SSHDATA_MPINT, key->u.dsa.q,
LTC_SSHDATA_MPINT, key->u.dsa.g,
LTC_SSHDATA_MPINT, key->u.dsa.y,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
goto cleanup;
}
key->u.dsa.qord = ltc_mp_unsigned_bin_size(key->u.dsa.q);
if ((err = dsa_int_validate_pqg(&key->u.dsa, &stat)) != CRYPT_OK) {
goto cleanup;
}
if (stat == 0) {
err = CRYPT_INVALID_PACKET;
goto cleanup;
}
if (type == pf_public) {
key->id = LTC_PKA_DSA;
key->u.dsa.type = PK_PUBLIC;
goto cleanup;
}
p += cur_len;
remaining -= cur_len;
cur_len = remaining;
if ((err = ssh_decode_sequence_multi(p, &cur_len,
LTC_SSHDATA_MPINT, key->u.dsa.x,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
goto cleanup;
}
key->id = LTC_PKA_DSA;
key->u.dsa.type = PK_PRIVATE;
cleanup:
if (err != CRYPT_OK) {
dsa_free(&key->u.dsa);
} else {
remaining -= cur_len;
*inlen -= remaining;
}
return err;
}
#endif
#ifdef LTC_MRSA
static int s_ssh_decode_rsa(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, enum pem_flags type)
{
int err;
void *tmp1, *tmp2;
unsigned long remaining, cur_len;
const unsigned char *p;
if ((err = rsa_init(&key->u.rsa)) != CRYPT_OK) {
return err;
}
p = in;
cur_len = *inlen;
remaining = *inlen;
/* ssh-rsa public and private keys contain `e` and `N` in a different order
* public contains `e`, then `N`
* private contains `N`, then `e`
* change the order later on if we import a public key */
if ((err = ssh_decode_sequence_multi(p, &cur_len,
LTC_SSHDATA_MPINT, key->u.rsa.N,
LTC_SSHDATA_MPINT, key->u.rsa.e,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
goto cleanup;
}
p += cur_len;
remaining -= cur_len;
cur_len = remaining;
if (type == pf_public) {
/* c.f. comment above */
void *exch = key->u.rsa.N;
key->u.rsa.N = key->u.rsa.e;
key->u.rsa.e = exch;
key->id = LTC_PKA_RSA;
key->u.rsa.type = PK_PUBLIC;
*inlen -= remaining;
goto cleanup;
}
if ((err = ltc_mp_init_multi(&tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) {
goto cleanup;
}
if ((err = ssh_decode_sequence_multi(p, &cur_len,
LTC_SSHDATA_MPINT, key->u.rsa.d,
LTC_SSHDATA_MPINT, key->u.rsa.qP,
LTC_SSHDATA_MPINT, key->u.rsa.p,
LTC_SSHDATA_MPINT, key->u.rsa.q,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
goto cleanup_tmps;
}
if ((err = ltc_mp_sub_d(key->u.rsa.p, 1, tmp1)) != CRYPT_OK) { goto cleanup_tmps; } /* tmp1 = q-1 */
if ((err = ltc_mp_sub_d(key->u.rsa.q, 1, tmp2)) != CRYPT_OK) { goto cleanup_tmps; } /* tmp2 = p-1 */
if ((err = ltc_mp_mod(key->u.rsa.d, tmp1, key->u.rsa.dP)) != CRYPT_OK) { goto cleanup_tmps; } /* dP = d mod p-1 */
if ((err = ltc_mp_mod(key->u.rsa.d, tmp2, key->u.rsa.dQ)) != CRYPT_OK) { goto cleanup_tmps; } /* dQ = d mod q-1 */
key->id = LTC_PKA_RSA;
key->u.rsa.type = PK_PRIVATE;
cleanup_tmps:
ltc_mp_deinit_multi(tmp2, tmp1, LTC_NULL);
cleanup:
if (err != CRYPT_OK) {
rsa_free(&key->u.rsa);
} else {
remaining -= cur_len;
*inlen -= remaining;
}
return err;
}
#endif
struct ssh_pka {
struct str name;
enum ltc_pka_id id;
int (*find)(const char*, const ltc_ecc_curve **);
int (*init)(const char*, ltc_pka_key*);
int (*decode)(const unsigned char*, unsigned long*, ltc_pka_key*, enum pem_flags);
};
struct ssh_pka ssh_pkas[] = {
#ifdef LTC_CURVE25519
{ SET_CSTR(.name, "ssh-ed25519"),
LTC_PKA_ED25519,
NULL,
NULL,
s_ssh_decode_ed25519 },
#endif
#ifdef LTC_MRSA
{ SET_CSTR(.name, "ssh-rsa"),
LTC_PKA_RSA,
NULL,
NULL,
s_ssh_decode_rsa },
#endif
#ifdef LTC_MDSA
{ SET_CSTR(.name, "ssh-dss"),
LTC_PKA_DSA,
NULL,
NULL,
s_ssh_decode_dsa },
#endif
#ifdef LTC_MECC
{ { NULL, 0 },
LTC_PKA_EC,
s_ssh_find_ecc,
s_ssh_find_init_ecc,
s_ssh_decode_ecdsa },
#endif
};
static int s_decode_key(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, char **comment, enum pem_flags type)
{
int err;
ulong32 check1, check2;
unsigned char pka[64];
unsigned long pkalen = sizeof(pka);
unsigned long remaining, cur_len;
const unsigned char *p;
unsigned long n;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != NULL);
LTC_ARGCHK(key != NULL);
p = in;
cur_len = *inlen;
remaining = *inlen;
if (type != pf_public) {
if ((err = ssh_decode_sequence_multi(p, &cur_len,
LTC_SSHDATA_UINT32, &check1,
LTC_SSHDATA_UINT32, &check2,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
return err;
}
if (check1 != check2) {
return CRYPT_INVALID_PACKET;
}
p += cur_len;
remaining -= cur_len;
cur_len = remaining;
}
if ((err = ssh_decode_sequence_multi(p, &cur_len,
LTC_SSHDATA_STRING, pka, &pkalen,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
return err;
}
p += cur_len;
remaining -= cur_len;
cur_len = remaining;
for (n = 0; n < sizeof(ssh_pkas)/sizeof(ssh_pkas[0]); ++n) {
if (ssh_pkas[n].name.p != NULL) {
if (pkalen != ssh_pkas[n].name.len
|| XMEMCMP(pka, ssh_pkas[n].name.p, ssh_pkas[n].name.len) != 0) continue;
} else {
if ((ssh_pkas[n].init == NULL) ||
(ssh_pkas[n].init((char*)pka, key) != CRYPT_OK)) continue;
}
if ((err = ssh_pkas[n].decode(p, &cur_len, key, type)) != CRYPT_OK) {
return err;
}
break;
}
if (n == sizeof(ssh_pkas)/sizeof(ssh_pkas[0])) {
return CRYPT_PK_INVALID_TYPE;
}
p += cur_len;
remaining -= cur_len;
cur_len = remaining;
if (cur_len != 0 && comment) {
unsigned long commentlen = cur_len;
char *c = XMALLOC(commentlen);
if (c == NULL) {
return CRYPT_MEM;
}
if ((err = ssh_decode_sequence_multi(p, &cur_len,
LTC_SSHDATA_STRING, c, &commentlen,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
return err;
}
if (commentlen == 0) {
XFREE(c);
} else {
*comment = c;
}
}
p += cur_len;
remaining -= cur_len;
return remaining ? padding_depad(p, &remaining, LTC_PAD_SSH) : CRYPT_OK;
}
static LTC_INLINE void skip_spaces(char **r, unsigned long *l)
{
while(*l && (**r == ' ' || **r == '\t')) {
(*r)++;
(*l)--;
}
}
static LTC_INLINE void skip_chars(char **r, unsigned long *l)
{
while(*l && (**r != ' ' && **r != '\t')) {
(*l)--;
if (**r == '\n' || **r == '\r') {
*l = 0;
} else {
(*r)++;
}
}
}
static LTC_INLINE void skip_to_eol(char **r, unsigned long *l)
{
while(*l && (**r != '\n' && **r != '\r')) {
(*l)--;
(*r)++;
}
}
static int s_parse_line(char *line, unsigned long *len, ltc_pka_key *key, char **comment)
{
int err;
unsigned long n, rlen, olen;
enum authorized_keys_elements {
ake_algo_name = 0,
ake_b64_encoded_key = 1,
ake_comment = 2
};
struct str elements[3] = { 0 };
char *r = line;
unsigned char *buf = NULL;
rlen = *len;
/* Chop up string into the three authorized_keys_elements */
for (n = 0; n < sizeof(elements)/sizeof(elements[0]) && rlen; ++n) {
skip_spaces(&r, &rlen);
elements[n].p = r;
if (n != 2)
skip_chars(&r, &rlen);
else
skip_to_eol(&r, &rlen);
elements[n].len = r - elements[n].p;
*r = '\0';
r++;
}
for (n = 0; n < sizeof(ssh_pkas)/sizeof(ssh_pkas[0]); ++n) {
if (ssh_pkas[n].name.p != NULL) {
if (elements[ake_algo_name].len != ssh_pkas[n].name.len
|| XMEMCMP(elements[ake_algo_name].p, ssh_pkas[n].name.p, ssh_pkas[n].name.len) != 0) continue;
} else {
if ((ssh_pkas[n].find == NULL) ||
(ssh_pkas[n].find(elements[ake_algo_name].p, NULL) != CRYPT_OK)) continue;
}
olen = elements[ake_b64_encoded_key].len;
buf = XMALLOC(olen);
if (buf == NULL) {
return CRYPT_MEM;
}
if ((err = base64_strict_decode(elements[ake_b64_encoded_key].p, elements[ake_b64_encoded_key].len, buf, &olen)) == CRYPT_OK) {
err = s_decode_key(buf, &olen, key, comment, pf_public);
if (err == CRYPT_OK && key->id != ssh_pkas[n].id) {
err = CRYPT_PK_INVALID_TYPE;
}
}
XFREE(buf);
if (err == CRYPT_OK) {
/* Only use the comment that was maybe in the text we just processed, in case when
* there was no comment inside the SSH key.
*/
if (*comment == NULL && elements[ake_comment].p) {
*comment = XMALLOC(elements[ake_comment].len + 1);
if (*comment == NULL) {
return CRYPT_MEM;
}
XMEMCPY(*comment, elements[ake_comment].p, elements[ake_comment].len);
(*comment)[elements[ake_comment].len] = '\0';
}
*len = r - line;
return CRYPT_OK;
}
}
return CRYPT_PK_INVALID_TYPE;
}
static int s_read_authorized_keys(const void *buf, unsigned long len, ssh_authorized_key_cb cb, void *ctx)
{
char *s;
int err;
unsigned long clen = len;
ltc_pka_key *key = XCALLOC(1, sizeof(*key));
char *comment = NULL;
void *cpy = XMALLOC(len);
if (key == NULL || cpy == NULL) {
if (cpy)
XFREE(cpy);
if (key)
XFREE(key);
return CRYPT_MEM;
}
XMEMCPY(cpy, buf, len);
s = cpy;
while (clen && (err = s_parse_line(s, &clen, key, &comment)) == CRYPT_OK) {
if (cb(key, comment, ctx)) {
break;
}
s += clen;
len -= clen;
clen = len;
key = XCALLOC(1, sizeof(*key));
if (key == NULL) {
err = CRYPT_MEM;
break;
}
if (comment) {
XFREE(comment);
comment = NULL;
}
}
if (comment)
XFREE(comment);
if (cpy)
XFREE(cpy);
if (key)
XFREE(key);
return err;
}
static int s_decrypt_private_keys(unsigned char *in, unsigned long *inlen,
unsigned char *tag, unsigned long taglen,
struct kdf_options *opts)
{
int err, cipher;
unsigned long symkey_len, iv_len;
unsigned char symkey[MAXBLOCKSIZE], *iv, iv_[8] = { 0 };
enum cipher_mode mode = opts->cipher->mode & cm_modes;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != NULL);
LTC_ARGCHK(opts != NULL);
if (mode != cm_stream) {
cipher = find_cipher(opts->cipher->algo);
if (cipher == -1) {
return CRYPT_INVALID_CIPHER;
}
iv = symkey + opts->cipher->keylen;
iv_len = mode == cm_gcm ? 12 : cipher_descriptor[cipher].block_length;
symkey_len = opts->cipher->keylen + iv_len;
} else {
iv = iv_;
iv_len = sizeof(iv_);
symkey_len = 64;
}
if (sizeof(symkey) < symkey_len) {
return CRYPT_OVERFLOW;
}
if ((err = bcrypt_pbkdf_openbsd(opts->pw.pw, opts->pw.l, opts->salt, opts->saltlen,
opts->num_rounds, find_hash("sha512"), symkey, &symkey_len)) != CRYPT_OK) {
return err;
}
err = pem_decrypt(in, inlen,
symkey, opts->cipher->keylen,
iv, iv_len,
tag, taglen,
opts->cipher, LTC_PAD_SSH);
zeromem(symkey, sizeof(symkey));
return err;
}
static int s_decode_header(unsigned char *in, unsigned long *inlen, struct kdf_options *opts)
{
int err;
unsigned char ciphername[64], kdfname[64], kdfoptions[128], pubkey1[2048];
unsigned long ciphernamelen = sizeof(ciphername), kdfnamelen = sizeof(kdfname);
unsigned long kdfoptionslen = sizeof(kdfoptions), pubkey1len = sizeof(pubkey1);
ulong32 num_keys;
unsigned long i;
void *magic = strstr((const char*)in, "openssh-key-v1");
unsigned long slen = XSTRLEN("openssh-key-v1");
unsigned char *start = &in[slen + 1];
unsigned long len = *inlen - slen - 1;
if (magic == NULL || magic != in) {
return CRYPT_INVALID_PACKET;
}
if ((err = ssh_decode_sequence_multi(start, &len,
LTC_SSHDATA_STRING, ciphername, &ciphernamelen,
LTC_SSHDATA_STRING, kdfname, &kdfnamelen,
LTC_SSHDATA_STRING, kdfoptions, &kdfoptionslen,
LTC_SSHDATA_UINT32, &num_keys,
LTC_SSHDATA_STRING, pubkey1, &pubkey1len,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
return err;
}
if (num_keys != 1) {
return CRYPT_INVALID_PACKET;
}
*inlen = len + slen + 1;
for (i = 0; i < ssh_ciphers_num; ++i) {
if (XSTRCMP((char*)ciphername, ssh_ciphers[i].name) == 0) {
opts->cipher = &ssh_ciphers[i];
break;
}
}
if (opts->cipher == NULL) {
return CRYPT_INVALID_CIPHER;
}
if (XSTRCMP((char*)kdfname, "none") == 0) {
/* NOP */
opts->name = "none";
} else if (XSTRCMP((char*)kdfname, "bcrypt") == 0) {
opts->name = "bcrypt";
opts->saltlen = sizeof(opts->salt);
len = kdfoptionslen;
if ((err = ssh_decode_sequence_multi(kdfoptions, &len,
LTC_SSHDATA_STRING, opts->salt, &opts->saltlen,
LTC_SSHDATA_UINT32, &opts->num_rounds,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
return err;
}
if (len != kdfoptionslen) {
return CRYPT_INPUT_TOO_LONG;
}
} else {
return CRYPT_INVALID_PACKET;
}
return err;
}
static const struct pem_header_id pem_openssh[] = {
{
SET_CSTR(.start, "-----BEGIN OPENSSH PRIVATE KEY-----"),
SET_CSTR(.end, "-----END OPENSSH PRIVATE KEY-----"),
.has_more_headers = no
},
{
SET_CSTR(.start, "---- BEGIN SSH2 PUBLIC KEY ----"),
SET_CSTR(.end, "---- END SSH2 PUBLIC KEY ----"),
.has_more_headers = maybe,
.flags = pf_public
},
};
static const unsigned long pem_openssh_num = sizeof(pem_openssh)/sizeof(pem_openssh[0]);
static int s_decode_openssh(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_ctx)
{
unsigned char *pem = NULL, *p, *privkey = NULL, *tag;
unsigned long n, w, l, privkey_len, taglen;
int err;
struct pem_headers hdr;
struct kdf_options opts = { 0 };
XMEMSET(k, 0, sizeof(*k));
w = LTC_PEM_READ_BUFSIZE * 2;
retry:
pem = XREALLOC(pem, w);
for (n = 0; n < pem_openssh_num; ++n) {
hdr.id = &pem_openssh[n];
err = pem_read(pem, &w, &hdr, g);
if (err == CRYPT_BUFFER_OVERFLOW) {
goto retry;
} else if (err == CRYPT_OK) {
break;
} else if (err != CRYPT_UNKNOWN_PEM) {
goto cleanup;
}
hdr.id = NULL;
}
/* id not found */
if (hdr.id == NULL) {
goto cleanup;
}
p = pem;
l = w;
if (hdr.id->flags != pf_public) {
if ((err = s_decode_header(pem, &w, &opts)) != CRYPT_OK) {
goto cleanup;
}
p = pem + w;
l -= w;
w = l;
privkey_len = l;
privkey = XMALLOC(privkey_len);
if (privkey == NULL) {
return CRYPT_MEM;
}
if ((err = ssh_decode_sequence_multi(p, &w,
LTC_SSHDATA_STRING, privkey, &privkey_len,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
goto cleanup;
}
if (XSTRCMP(opts.name, "none") != 0) {
if ((pw_ctx == NULL) || (pw_ctx->callback == NULL)) {
err = CRYPT_PW_CTX_MISSING;
goto cleanup;
}
if (pw_ctx->callback(&opts.pw.pw, &opts.pw.l, pw_ctx->userdata)) {
err = CRYPT_ERROR;
goto cleanup;
}
tag = p + w;
taglen = l - w;
w = privkey_len;
if ((err = s_decrypt_private_keys(privkey, &privkey_len,
tag, taglen,
&opts)) != CRYPT_OK) {
goto cleanup;
}
zeromem(opts.pw.pw, opts.pw.l);
}
p = privkey;
w = privkey_len;
}
if ((err = s_decode_key(p, &w, k, NULL, hdr.id->flags)) != CRYPT_OK) {
goto cleanup;
}
cleanup:
password_free(&opts.pw, pw_ctx);
if (privkey) {
zeromem(privkey, privkey_len);
XFREE(privkey);
}
XFREE(pem);
return err;
}
#ifndef LTC_NO_FILE
int pem_decode_openssh_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx)
{
LTC_ARGCHK(f != NULL);
LTC_ARGCHK(k != NULL);
{
struct get_char g = { .get = pem_get_char_from_file, .data.f = f };
return s_decode_openssh(&g, k, pw_ctx);
}
}
int ssh_read_authorized_keys_filehandle(FILE *f, ssh_authorized_key_cb cb, void *ctx)
{
size_t tot_data;
void *buf;
int err;
LTC_ARGCHK(f != NULL);
LTC_ARGCHK(cb != NULL);
fseek(f, 0, SEEK_END);
tot_data = ftell(f);
rewind(f);
buf = XMALLOC(tot_data);
if (buf == NULL) {
return CRYPT_MEM;
}
if (fread(buf, 1, tot_data, f) != tot_data) {
err = CRYPT_ERROR;
} else {
err = s_read_authorized_keys(buf, tot_data, cb, ctx);
}
XFREE(buf);
return err;
}
#endif /* LTC_NO_FILE */
int pem_decode_openssh(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx)
{
LTC_ARGCHK(buf != NULL);
LTC_ARGCHK(len != 0);
LTC_ARGCHK(k != NULL);
{
struct get_char g = { .get = pem_get_char_from_buf, SET_BUFP(.data.buf, buf, len) };
return s_decode_openssh(&g, k, pw_ctx);
}
}
int ssh_read_authorized_keys(const void *buf, unsigned long len, ssh_authorized_key_cb cb, void *ctx)
{
LTC_ARGCHK(buf != NULL);
LTC_ARGCHK(len != 0);
LTC_ARGCHK(cb != NULL);
return s_read_authorized_keys(buf, len, cb, ctx);
}
#endif /* defined(LTC_PEM_SSH) */
#pragma clang diagnostic pop

View File

@@ -0,0 +1,88 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
#ifdef LTC_PKCS_12
int pkcs12_kdf( int hash_id,
const unsigned char *pw, unsigned long pwlen,
const unsigned char *salt, unsigned long saltlen,
unsigned int iterations, unsigned char purpose,
unsigned char *out, unsigned long outlen)
{
unsigned long u = hash_descriptor[hash_id].hashsize;
unsigned long v = hash_descriptor[hash_id].blocksize;
unsigned long c = (outlen + u - 1) / u;
unsigned long Slen = ((saltlen + v - 1) / v) * v;
unsigned long Plen = ((pwlen + v - 1) / v) * v;
unsigned long k = (Plen + Slen) / v;
unsigned long Alen, keylen = 0;
unsigned int tmp, i, j, n;
unsigned char ch;
unsigned char D[MAXBLOCKSIZE], A[MAXBLOCKSIZE], B[MAXBLOCKSIZE];
unsigned char *I, *key;
int err = CRYPT_ERROR;
LTC_ARGCHK(pw != NULL);
LTC_ARGCHK(salt != NULL);
LTC_ARGCHK(out != NULL);
key = XMALLOC(u * c);
I = XMALLOC(Plen + Slen);
if (key == NULL || I == NULL) goto DONE;
zeromem(key, u * c);
for (i = 0; i < v; i++) D[i] = purpose; /* D - diversifier */
for (i = 0; i < Slen; i++) I[i] = salt[i % saltlen];
for (i = 0; i < Plen; i++) I[Slen + i] = pw[i % pwlen]; /* I = Salt || Pass */
for (i = 0; i < c; i++) {
Alen = sizeof(A);
err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, LTC_NULL); /* A = HASH(D || I) */
if (err != CRYPT_OK) goto DONE;
for (j = 1; j < iterations; j++) {
err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */
if (err != CRYPT_OK) goto DONE;
}
/* fill buffer B with A */
for (j = 0; j < v; j++) B[j] = A[j % Alen];
/* B += 1 */
for (j = v; j > 0; j--) {
if (++B[j - 1] != 0) break;
}
/* I_n += B */
for (n = 0; n < k; n++) {
ch = 0;
for (j = v; j > 0; j--) {
tmp = I[n * v + j - 1] + B[j - 1] + ch;
ch = (unsigned char)((tmp >> 8) & 0xFF);
I[n * v + j - 1] = (unsigned char)(tmp & 0xFF);
}
}
/* store derived key block */
XMEMCPY(&key[keylen], A, Alen);
keylen += Alen;
}
XMEMCPY(out, key, outlen);
err = CRYPT_OK;
DONE:
if (I) {
zeromem(I, Plen + Slen);
XFREE(I);
}
if (key) {
zeromem(key, u * c);
XFREE(key);
}
return err;
}
#endif
#pragma clang diagnostic pop

View File

@@ -0,0 +1,59 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#ifdef LTC_PKCS_12
int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen) {
unsigned long len = 0;
const unsigned char* in_end = in + inlen;
const ulong32 offset[6] = {
0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL
};
int err = CRYPT_ERROR;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
while (in < in_end) {
ulong32 ch = 0;
unsigned short extra = 0; /* 0 */
if (*in >= 192) extra++; /* 1 */
if (*in >= 224) extra++; /* 2 */
if (*in >= 240) extra++; /* 3 */
if (*in >= 248) extra++; /* 4 */
if (*in >= 252) extra++; /* 5 */
if (in + extra >= in_end) goto ERROR;
switch (extra) {
case 5: ch += *in++; ch <<= 6;
/* FALLTHROUGH */
case 4: ch += *in++; ch <<= 6;
/* FALLTHROUGH */
case 3: ch += *in++; ch <<= 6;
/* FALLTHROUGH */
case 2: ch += *in++; ch <<= 6;
/* FALLTHROUGH */
case 1: ch += *in++; ch <<= 6;
/* FALLTHROUGH */
case 0: ch += *in++;
}
ch -= offset[extra];
if (ch > 0xFFFF) goto ERROR;
if (*outlen >= len + 2) {
out[len] = (unsigned short)((ch >> 8) & 0xFF);
out[len + 1] = (unsigned char)(ch & 0xFF);
}
len += 2;
}
err = len > *outlen ? CRYPT_BUFFER_OVERFLOW : CRYPT_OK;
*outlen = len;
ERROR:
return err;
}
#endif

View File

@@ -0,0 +1,185 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file pkcs_5_1.c
PKCS #5, Algorithm #1, Tom St Denis
*/
#ifdef LTC_PKCS_5
/**
Execute PKCS #5 v1 in strict or OpenSSL EVP_BytesToKey()-compat mode.
PKCS#5 v1 specifies that the output key length can be no larger than
the hash output length. OpenSSL unilaterally extended that by repeating
the hash process on a block-by-block basis for as long as needed to make
bigger keys. If you want to be compatible with KDF for e.g. "openssl enc",
you'll want that.
If you want strict PKCS behavior, turn openssl_compat off. Or (more
likely), use one of the convenience functions below.
@param password The password (or key)
@param password_len The length of the password (octet)
@param salt The salt (or nonce) which is 8 octets long
@param iteration_count The PKCS #5 v1 iteration count
@param hash_idx The index of the hash desired
@param out [out] The destination for this algorithm
@param outlen [in/out] The max size and resulting size of the algorithm output
@param openssl_compat [in] Whether or not to grow the key to the buffer size ala OpenSSL
@return CRYPT_OK if successful
*/
static int s_pkcs_5_alg1_common(const unsigned char *password,
unsigned long password_len,
const unsigned char *salt,
int iteration_count, int hash_idx,
unsigned char *out, unsigned long *outlen,
int openssl_compat)
{
int err;
unsigned long x;
hash_state *md;
unsigned char *buf;
/* Storage vars in case we need to support > hashsize (OpenSSL compat) */
unsigned long block = 0, iter;
/* How many bytes to put in the outbut buffer (convenience calc) */
unsigned long outidx = 0, nb = 0;
LTC_ARGCHK(password != NULL);
LTC_ARGCHK(salt != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
if (iteration_count <= 0) {
return CRYPT_INVALID_ARG;
}
/* test hash IDX */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
return err;
}
/* allocate memory */
md = XMALLOC(sizeof(hash_state));
buf = XMALLOC(MAXBLOCKSIZE);
if (md == NULL || buf == NULL) {
if (md != NULL) {
XFREE(md);
}
if (buf != NULL) {
XFREE(buf);
}
return CRYPT_MEM;
}
while(block * hash_descriptor[hash_idx].hashsize < *outlen) {
/* hash initial (maybe previous hash) + password + salt */
if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {
goto LBL_ERR;
}
/* in OpenSSL mode, we first hash the previous result for blocks 2-n */
if (openssl_compat && block) {
if ((err = hash_descriptor[hash_idx].process(md, buf, hash_descriptor[hash_idx].hashsize)) != CRYPT_OK) {
goto LBL_ERR;
}
}
if ((err = hash_descriptor[hash_idx].process(md, password, password_len)) != CRYPT_OK) {
goto LBL_ERR;
}
if ((err = hash_descriptor[hash_idx].process(md, salt, 8)) != CRYPT_OK) {
goto LBL_ERR;
}
if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) {
goto LBL_ERR;
}
iter = iteration_count;
while (--iter) {
/* code goes here. */
x = MAXBLOCKSIZE;
if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx].hashsize, buf, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
}
/* limit the size of the copy to however many bytes we have left in
the output buffer (and how many bytes we have to copy) */
outidx = block*hash_descriptor[hash_idx].hashsize;
nb = hash_descriptor[hash_idx].hashsize;
if(outidx+nb > *outlen) {
nb = *outlen - outidx;
}
if(nb > 0) {
XMEMCPY(out+outidx, buf, nb);
}
block++;
if (!openssl_compat) {
break;
}
}
/* In strict mode, we always return the hashsize, in compat we filled it
as much as was requested, so we leave it alone. */
if(!openssl_compat) {
*outlen = hash_descriptor[hash_idx].hashsize;
}
err = CRYPT_OK;
LBL_ERR:
#ifdef LTC_CLEAN_STACK
zeromem(buf, MAXBLOCKSIZE);
zeromem(md, sizeof(hash_state));
#endif
XFREE(buf);
XFREE(md);
return err;
}
/**
Execute PKCS #5 v1 - Strict mode (no OpenSSL-compatible extension)
@param password The password (or key)
@param password_len The length of the password (octet)
@param salt The salt (or nonce) which is 8 octets long
@param iteration_count The PKCS #5 v1 iteration count
@param hash_idx The index of the hash desired
@param out [out] The destination for this algorithm
@param outlen [in/out] The max size and resulting size of the algorithm output
@return CRYPT_OK if successful
*/
int pkcs_5_alg1(const unsigned char *password, unsigned long password_len,
const unsigned char *salt,
int iteration_count, int hash_idx,
unsigned char *out, unsigned long *outlen)
{
return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count,
hash_idx, out, outlen, 0);
}
/**
Execute PKCS #5 v1 - OpenSSL-extension-compatible mode
Use this one if you need to derive keys as "openssl enc" does by default.
OpenSSL (for better or worse), uses MD5 as the hash and iteration_count=1.
@param password The password (or key)
@param password_len The length of the password (octet)
@param salt The salt (or nonce) which is 8 octets long
@param iteration_count The PKCS #5 v1 iteration count
@param hash_idx The index of the hash desired
@param out [out] The destination for this algorithm
@param outlen [in/out] The max size and resulting size of the algorithm output
@return CRYPT_OK if successful
*/
int pkcs_5_alg1_openssl(const unsigned char *password,
unsigned long password_len,
const unsigned char *salt,
int iteration_count, int hash_idx,
unsigned char *out, unsigned long *outlen)
{
return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count,
hash_idx, out, outlen, 1);
}
#endif

View File

@@ -0,0 +1,121 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file pkcs_5_2.c
PKCS #5, Algorithm #2, Tom St Denis
*/
#ifdef LTC_PKCS_5
/**
Execute PKCS #5 v2
@param password The input password (or key)
@param password_len The length of the password (octets)
@param salt The salt (or nonce)
@param salt_len The length of the salt (octets)
@param iteration_count # of iterations desired for PKCS #5 v2 [read specs for more]
@param hash_idx The index of the hash desired
@param out [out] The destination for this algorithm
@param outlen [in/out] The max size and resulting size of the algorithm output
@return CRYPT_OK if successful
*/
int pkcs_5_alg2(const unsigned char *password, unsigned long password_len,
const unsigned char *salt, unsigned long salt_len,
int iteration_count, int hash_idx,
unsigned char *out, unsigned long *outlen)
{
int err, itts;
ulong32 blkno;
unsigned long stored, left, x, y;
unsigned char *buf[2];
hmac_state *hmac;
LTC_ARGCHK(password != NULL);
LTC_ARGCHK(salt != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
if (iteration_count <= 0) {
return CRYPT_INVALID_ARG;
}
/* test hash IDX */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
return err;
}
buf[0] = XMALLOC(MAXBLOCKSIZE * 2);
hmac = XMALLOC(sizeof(hmac_state));
if (hmac == NULL || buf[0] == NULL) {
if (hmac != NULL) {
XFREE(hmac);
}
if (buf[0] != NULL) {
XFREE(buf[0]);
}
return CRYPT_MEM;
}
/* buf[1] points to the second block of MAXBLOCKSIZE bytes */
buf[1] = buf[0] + MAXBLOCKSIZE;
left = *outlen;
blkno = 1;
stored = 0;
while (left != 0) {
/* process block number blkno */
zeromem(buf[0], MAXBLOCKSIZE*2);
/* store current block number and increment for next pass */
STORE32H(blkno, buf[1]);
++blkno;
/* get PRF(P, S||int(blkno)) */
if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) {
goto LBL_ERR;
}
if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) {
goto LBL_ERR;
}
if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) {
goto LBL_ERR;
}
x = MAXBLOCKSIZE;
if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) {
goto LBL_ERR;
}
/* now compute repeated and XOR it in buf[1] */
XMEMCPY(buf[1], buf[0], x);
for (itts = 1; itts < iteration_count; ++itts) {
if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) {
goto LBL_ERR;
}
for (y = 0; y < x; y++) {
buf[1][y] ^= buf[0][y];
}
}
/* now emit upto x bytes of buf[1] to output */
for (y = 0; y < x && left != 0; ++y) {
out[stored++] = buf[1][y];
--left;
}
}
*outlen = stored;
err = CRYPT_OK;
LBL_ERR:
#ifdef LTC_CLEAN_STACK
zeromem(buf[0], MAXBLOCKSIZE*2);
zeromem(hmac, sizeof(hmac_state));
#endif
XFREE(hmac);
XFREE(buf[0]);
return err;
}
#endif

View File

@@ -0,0 +1,224 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file hkdf_test.c
PKCS #5 support, self-test, Steffen Jaeckel
*/
#ifdef LTC_PKCS_5
/*
TEST CASES SOURCE:
Internet Engineering Task Force (IETF) S. Josefsson
Request for Comments: 6070 SJD AB
Category: Informational January 2011
ISSN: 2070-1721
*/
/**
PKCS #5 self-test
@return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled.
*/
int pkcs_5_test (void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
typedef struct {
const char* P;
unsigned long P_len;
const char* S;
unsigned long S_len;
int c;
unsigned long dkLen;
unsigned char DK[40];
} case_item;
static const case_item cases_5_2[] = {
{
"password",
8,
"salt",
4,
1,
20,
{ 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
0x2f, 0xe0, 0x37, 0xa6 }
},
{
"password",
8,
"salt",
4,
2,
20,
{ 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
0xd8, 0xde, 0x89, 0x57 }
},
#ifdef LTC_TEST_EXT
{
"password",
8,
"salt",
4,
4096,
20,
{ 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
0x65, 0xa4, 0x29, 0xc1 }
},
{
"password",
8,
"salt",
4,
16777216,
20,
{ 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
0x26, 0x34, 0xe9, 0x84 }
},
{
"passwordPASSWORDpassword",
25,
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
36,
4096,
25,
{ 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
0x38 }
},
{
"pass\0word",
9,
"sa\0lt",
5,
4096,
16,
{ 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }
},
#endif /* LTC_TEST_EXT */
};
static const case_item cases_5_1[] = {
{
"password",
8,
"saltsalt", /* must be 8 octects */
8, /* ignored by alg1 */
1,
20,
{ 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c,
0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 }
},
};
static const case_item cases_5_1o[] = {
{
"password",
8,
"saltsalt", /* must be 8 octects */
8, /* ignored by alg1_openssl */
1,
20,
{ 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c,
0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 }
},
{
"password",
8,
"saltsalt", /* must be 8 octects */
8, /* ignored by alg1_openssl */
1,
30,
{ 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c,
0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44,
0xf0, 0xbf, 0xf4, 0xc1, 0x2c, 0xf3, 0x59, 0x6f, 0xc0, 0x0b }
}
};
unsigned char DK[40];
unsigned long dkLen;
int i, err;
int tested=0, failed=0;
int hash = find_hash("sha1");
if (hash == -1)
{
#ifdef LTC_TEST_DBG
printf("PKCS#5 test failed: 'sha1' hash not found\n");
#endif
return CRYPT_ERROR;
}
/* testing alg 2 */
for(i=0; i < (int)(sizeof(cases_5_2) / sizeof(cases_5_2[0])); i++) {
++tested;
dkLen = cases_5_2[i].dkLen;
if((err = pkcs_5_alg2((unsigned char*)cases_5_2[i].P, cases_5_2[i].P_len,
(unsigned char*)cases_5_2[i].S, cases_5_2[i].S_len,
cases_5_2[i].c, hash,
DK, &dkLen)) != CRYPT_OK) {
LTC_UNUSED_PARAM(err);
#ifdef LTC_TEST_DBG
printf("\npkcs_5_alg2() #%d: Failed/1 (%s)\n", i, error_to_string(err));
#endif
++failed;
}
else if (compare_testvector(DK, dkLen, cases_5_2[i].DK, cases_5_2[i].dkLen, "PKCS#5_2", i)) {
++failed;
}
}
/* testing alg 1 */
for(i=0; i < (int)(sizeof(cases_5_1) / sizeof(case_item)); i++, tested++) {
dkLen = cases_5_1[i].dkLen;
if((err = pkcs_5_alg1((unsigned char*)cases_5_1[i].P, cases_5_1[i].P_len,
(unsigned char*)cases_5_1[i].S,
cases_5_1[i].c, hash,
DK, &dkLen)) != CRYPT_OK) {
LTC_UNUSED_PARAM(err);
#ifdef LTC_TEST_DBG
printf("\npkcs_5_alg1() #%d: Failed/1 (%s)\n", i, error_to_string(err));
#endif
++failed;
}
else if (compare_testvector(DK, dkLen, cases_5_1[i].DK, cases_5_1[i].dkLen, "PKCS#5_1", i)) {
++failed;
}
}
/* testing alg 1_openssl */
for(i = 0; i < (int)(sizeof(cases_5_1o) / sizeof(cases_5_1o[0])); i++, tested++) {
dkLen = cases_5_1o[i].dkLen;
if ((err = pkcs_5_alg1_openssl((unsigned char*)cases_5_1o[i].P, cases_5_1o[i].P_len,
(unsigned char*)cases_5_1o[i].S,
cases_5_1o[i].c, hash,
DK, &dkLen)) != CRYPT_OK) {
LTC_UNUSED_PARAM(err);
#ifdef LTC_TEST_DBG
printf("\npkcs_5_alg1_openssl() #%d: Failed/1 (%s)\n", i, error_to_string(err));
#endif
++failed;
}
else if (compare_testvector(DK, dkLen, cases_5_1o[i].DK, cases_5_1o[i].dkLen, "PKCS#5_1o", i)) {
++failed;
}
}
return (failed != 0) ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK;
#endif
}
#endif

View File

@@ -0,0 +1,164 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file ssh_decode_sequence_multi.c
SSH data type representation as per RFC4251, Russ Williams
*/
#ifdef LTC_SSH
/**
Decode a SSH sequence using a VA list
@param in The input buffer
@param inlen [in/out] The length of the input buffer and on output the amount of decoded data
@remark <...> is of the form <type, data*> (int, <unsigned char*,ulong32*,ulong64*>) except for string&name-list <type, data, size*> (int, void*, unsigned long*)
@return CRYPT_OK on success
*/
int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...)
{
int err;
va_list args;
ssh_data_type type;
void *vdata;
unsigned char *cdata;
char *sdata;
ulong32 *u32data;
ulong64 *u64data;
unsigned long *bufsize;
ulong32 size;
unsigned long remaining;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != NULL);
remaining = *inlen;
/* Decode values from buffer */
va_start(args, inlen);
while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
/* Size of length field */
if (type == LTC_SSHDATA_STRING ||
type == LTC_SSHDATA_NAMELIST ||
type == LTC_SSHDATA_MPINT)
{
/* Check we'll not read too far */
if (remaining < 4) {
err = CRYPT_BUFFER_OVERFLOW;
goto error;
}
}
/* Calculate (or read) length of data */
size = 0xFFFFFFFFU;
switch (type) {
case LTC_SSHDATA_BYTE:
case LTC_SSHDATA_BOOLEAN:
size = 1;
break;
case LTC_SSHDATA_UINT32:
size = 4;
break;
case LTC_SSHDATA_UINT64:
size = 8;
break;
case LTC_SSHDATA_STRING:
case LTC_SSHDATA_NAMELIST:
case LTC_SSHDATA_MPINT:
LOAD32H(size, in);
in += 4;
remaining -= 4;
break;
case LTC_SSHDATA_EOL:
/* Should never get here */
err = CRYPT_INVALID_ARG;
goto error;
}
/* Check we'll not read too far */
if (remaining < size) {
err = CRYPT_BUFFER_OVERFLOW;
goto error;
} else {
remaining -= size;
}
vdata = va_arg(args, void*);
if (vdata == NULL) {
err = CRYPT_INVALID_ARG;
goto error;
}
/* Read data */
switch (type) {
case LTC_SSHDATA_BYTE:
cdata = vdata;
*cdata = *in++;
break;
case LTC_SSHDATA_BOOLEAN:
cdata = vdata;
/*
The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be
interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1.
*/
*cdata = (*in++)?1:0;
break;
case LTC_SSHDATA_UINT32:
u32data = vdata;
LOAD32H(*u32data, in);
in += 4;
break;
case LTC_SSHDATA_UINT64:
u64data = vdata;
LOAD64H(*u64data, in);
in += 8;
break;
case LTC_SSHDATA_STRING:
case LTC_SSHDATA_NAMELIST:
sdata = vdata;
bufsize = va_arg(args, unsigned long*);
if (bufsize == NULL) {
err = CRYPT_INVALID_ARG;
goto error;
}
if (size + 1 >= *bufsize) {
err = CRYPT_BUFFER_OVERFLOW;
goto error;
}
if (size > 0) {
XMEMCPY(sdata, (const char *)in, size);
}
sdata[size] = '\0';
*bufsize = size;
in += size;
break;
case LTC_SSHDATA_MPINT:
if (size == 0) {
if ((err = ltc_mp_set(vdata, 0)) != CRYPT_OK) { goto error; }
} else if ((in[0] & 0x80) != 0) {
/* Negative number - not supported */
err = CRYPT_INVALID_PACKET;
goto error;
} else {
if ((err = ltc_mp_read_unsigned_bin(vdata, in, size)) != CRYPT_OK) { goto error; }
}
in += size;
break;
case LTC_SSHDATA_EOL:
/* Should never get here */
err = CRYPT_INVALID_ARG;
goto error;
}
}
err = CRYPT_OK;
*inlen -= remaining;
error:
va_end(args);
return err;
}
#endif

View File

@@ -0,0 +1,163 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
/**
@file ssh_encode_sequence_multi.c
SSH data type representation as per RFC4251, Russ Williams
*/
#ifdef LTC_SSH
/**
Encode a SSH sequence using a VA list
@param out [out] Destination for data
@param outlen [in/out] Length of buffer and resulting length of output
@remark <...> is of the form <type, data> (int, <int,ulong32,ulong64>) except for string&name-list <type, data, size> (int, void*, unsigned long)
@return CRYPT_OK on success
*/
int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
{
int err;
va_list args;
ulong32 size;
ssh_data_type type;
void *vdata;
const char *sdata;
int idata;
ulong32 u32data;
ulong64 u64data;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
/* Check values and calculate output size */
size = 0;
va_start(args, outlen);
while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
switch (type) {
case LTC_SSHDATA_BYTE:
case LTC_SSHDATA_BOOLEAN: /* Both stored as 1 byte */
LTC_UNUSED_PARAM( va_arg(args, int) );
size++;
break;
case LTC_SSHDATA_UINT32:
LTC_UNUSED_PARAM( va_arg(args, ulong32) );
size += 4;
break;
case LTC_SSHDATA_UINT64:
LTC_UNUSED_PARAM( va_arg(args, ulong64) );
size += 8;
break;
case LTC_SSHDATA_STRING:
case LTC_SSHDATA_NAMELIST:
LTC_UNUSED_PARAM( va_arg(args, char*) );
size += va_arg(args, unsigned long);
size += 4;
break;
case LTC_SSHDATA_MPINT:
vdata = va_arg(args, void*);
/* Calculate size */
size += 4;
if (ltc_mp_iszero(vdata) != LTC_MP_YES) {
size += ltc_mp_unsigned_bin_size(vdata);
if ((ltc_mp_count_bits(vdata) & 7) == 0) size++; /* Zero padding if high bit set */
}
break;
case LTC_SSHDATA_EOL: /* Should never get here */
err = CRYPT_INVALID_ARG;
goto error;
}
}
va_end(args);
/* Check we have sufficient space */
if (*outlen < size) {
*outlen = size;
err = CRYPT_BUFFER_OVERFLOW;
goto errornoargs;
}
*outlen = size;
/* Encode values into buffer */
va_start(args, outlen);
while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
switch (type) {
case LTC_SSHDATA_BYTE:
idata = va_arg(args, int);
*out++ = (unsigned char)(idata & 255);
break;
case LTC_SSHDATA_BOOLEAN:
idata = va_arg(args, int);
/*
The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be
interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1.
*/
*out++ = (idata)?1:0;
break;
case LTC_SSHDATA_UINT32:
u32data = va_arg(args, ulong32);
STORE32H(u32data, out);
out += 4;
break;
case LTC_SSHDATA_UINT64:
u64data = va_arg(args, ulong64);
STORE64H(u64data, out);
out += 8;
break;
case LTC_SSHDATA_STRING:
case LTC_SSHDATA_NAMELIST:
sdata = va_arg(args, char*);
size = va_arg(args, unsigned long);
STORE32H(size, out);
out += 4;
XMEMCPY(out, sdata, size);
out += size;
break;
case LTC_SSHDATA_MPINT:
vdata = va_arg(args, void*);
if (ltc_mp_iszero(vdata) == LTC_MP_YES) {
STORE32H(0, out);
out += 4;
} else {
size = ltc_mp_unsigned_bin_size(vdata);
if ((ltc_mp_count_bits(vdata) & 7) == 0) {
/* Zero padding if high bit set */
STORE32H(size+1, out);
out += 4;
*out++ = 0;
} else {
STORE32H(size, out);
out += 4;
}
if (ltc_mp_to_unsigned_bin(vdata, out) != CRYPT_OK) {
err = CRYPT_ERROR;
goto error;
}
out += size;
}
break;
case LTC_SSHDATA_EOL: /* Should never get here */
err = CRYPT_INVALID_ARG;
goto error;
}
}
err = CRYPT_OK;
error:
va_end(args);
errornoargs:
return err;
}
#endif
#pragma clang diagnostic pop

View File

@@ -0,0 +1,22 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file zeromem.c
Zero a block of memory, Tom St Denis
*/
/**
Zero a block of memory
@param out The destination of the area to zero
@param outlen The length of the area to zero (octets)
*/
void zeromem(volatile void *out, size_t outlen)
{
volatile char *mem = out;
LTC_ARGCHKVD(out != NULL);
while (outlen-- > 0) {
*mem++ = '\0';
}
}