2
0

Fix up and clean up base64 & aes code.

This commit is contained in:
Maarten Billemont 2017-08-05 21:52:00 -04:00
parent 5f2e1611f1
commit 23491faccc
4 changed files with 96 additions and 59 deletions

View File

@ -78,37 +78,35 @@ static const unsigned char pr2six[256] =
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
}; };
size_t Base64decode_len(const char *bufcoded) { size_t mpw_base64_decode_max(const char *b64Text) {
size_t nbytesdecoded; register const uint8_t *bufin;
register const unsigned char *bufin;
register int nprbytes; register int nprbytes;
bufin = (const unsigned char *)bufcoded; bufin = (uint8_t *)b64Text;
while (pr2six[*(bufin++)] <= 63); while (pr2six[*(bufin++)] <= 63);
nprbytes = (int)(bufin - (const unsigned char *)bufcoded) - 1; nprbytes = (int)(bufin - (uint8_t *)b64Text) - 1;
nbytesdecoded = (size_t)(((nprbytes + 3) / 4) * 3); return (size_t)(((nprbytes + 3) / 4) * 3);
return nbytesdecoded;
} }
int Base64decode(uint8_t *bufplain, const char *bufcoded) { int mpw_base64_decode(uint8_t *plainBuf, size_t plainMax, const char *b64Text) {
int nbytesdecoded; register const uint8_t *bufin;
register const unsigned char *bufin; register uint8_t *bufout;
register unsigned char *bufout;
register int nprbytes; register int nprbytes;
bufin = (const unsigned char *)bufcoded; bufin = (uint8_t *)b64Text;
while (pr2six[*(bufin++)] <= 63); while (pr2six[*(bufin++)] <= 63);
nprbytes = (int)(bufin - (const unsigned char *)bufcoded) - 1; nprbytes = (int)(bufin - (uint8_t *)b64Text) - 1;
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
bufout = bufplain; bufout = plainBuf;
bufin = (const unsigned char *)bufcoded; bufin = (uint8_t *)b64Text;
while (nprbytes > 4) { while (nprbytes > 4) {
if (bufout + 2 >= plainBuf + plainMax)
return -1;
*(bufout++) = (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); *(bufout++) = (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
*(bufout++) = (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); *(bufout++) = (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
*(bufout++) = (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); *(bufout++) = (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
@ -118,54 +116,67 @@ int Base64decode(uint8_t *bufplain, const char *bufcoded) {
/* Note: (nprbytes == 1) would be an error, so just ingore that case */ /* Note: (nprbytes == 1) would be an error, so just ingore that case */
if (nprbytes > 1) { if (nprbytes > 1) {
if (bufout >= plainBuf + plainMax)
return -1;
*(bufout++) = (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); *(bufout++) = (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
} }
if (nprbytes > 2) { if (nprbytes > 2) {
if (bufout >= plainBuf + plainMax)
return -1;
*(bufout++) = (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); *(bufout++) = (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
} }
if (nprbytes > 3) { if (nprbytes > 3) {
if (bufout >= plainBuf + plainMax)
return -1;
*(bufout++) = (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); *(bufout++) = (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
} }
nbytesdecoded -= (4 - nprbytes) & 3; return (int)(bufout - plainBuf);
return nbytesdecoded;
} }
static const char basis_64[] = static const char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
size_t Base64encode_len(size_t len) { size_t mpw_base64_encode_max(size_t plainSize) {
return ((len + 2) / 3 * 4); // Every 3 plain bytes yield 4 b64 chars => len = 4 * ceil(plainSize / 3)
return 4 /*chars*/ * (plainSize + 3 /*bytes*/ - 1) / 3 /*bytes*/;
} }
int Base64encode(char *encoded, const uint8_t *string, size_t len) { int mpw_base64_encode(char *b64Text, size_t b64Max, const uint8_t *plainBuf, size_t plainSize) {
int i; int i;
char *p; char *p;
p = encoded; p = b64Text;
for (i = 0; i < len - 2; i += 3) { for (i = 0; i < plainSize - 2; i += 3) {
*p++ = basis_64[(string[i] >> 2) & 0x3F]; if (p >= b64Text + b64Max)
*p++ = basis_64[((string[i] & 0x3) << 4) | return -1;
((string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2) | *p++ = basis_64[(plainBuf[i] >> 2) & 0x3F];
((string[i + 2] & 0xC0) >> 6)]; *p++ = basis_64[((plainBuf[i] & 0x3) << 4) |
*p++ = basis_64[string[i + 2] & 0x3F]; ((plainBuf[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((plainBuf[i + 1] & 0xF) << 2) |
((plainBuf[i + 2] & 0xC0) >> 6)];
*p++ = basis_64[plainBuf[i + 2] & 0x3F];
} }
if (i < len) { if (i < plainSize) {
*p++ = basis_64[(string[i] >> 2) & 0x3F]; if (p + 3 >= b64Text + b64Max)
if (i == (len - 1)) { return -1;
*p++ = basis_64[((string[i] & 0x3) << 4)];
*p++ = basis_64[(plainBuf[i] >> 2) & 0x3F];
if (i == (plainSize - 1)) {
*p++ = basis_64[((plainBuf[i] & 0x3) << 4)];
*p++ = '='; *p++ = '=';
} }
else { else {
*p++ = basis_64[((string[i] & 0x3) << 4) | *p++ = basis_64[((plainBuf[i] & 0x3) << 4) |
((string[i + 1] & 0xF0) >> 4)]; ((plainBuf[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2)]; *p++ = basis_64[((plainBuf[i + 1] & 0xF) << 2)];
} }
*p++ = '='; *p++ = '=';
} }
return (int)(p - encoded); *p = '\0';
return (int)(p - b64Text);
} }

View File

@ -57,8 +57,23 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
size_t Base64decode_len(const char *bufcoded); /**
int Base64decode(uint8_t *bufplain, const char *bufcoded); * @return The amount of bytes needed to decode the given b64Text.
*/
size_t mpw_base64_decode_max(const char *b64Text);
/** Decodes a base-64 encoded string into a plain byte buffer.
* @param plainMax the maximum amount of bytes to write to plainBuf.
* @return The amount of bytes that were written to plainBuf or -1 if this amount would have exceeded plainMax.
*/
int mpw_base64_decode(uint8_t *plainBuf, size_t plainMax, const char *b64Text);
size_t Base64encode_len(size_t len); /**
int Base64encode(char *encoded, const uint8_t *string, size_t len); * @return The amount of characters needed to encode a plainBuf of the given size as base-64 (excluding the terminating NUL).
*/
size_t mpw_base64_encode_max(size_t plainSize);
/** Encodes a plain byte buffer into a base-64 encoded string.
* @param b64Max the maximum amount of characters to write to b64Text, excluding the terminating NUL.
* @return The amount of characters that were written to b64Text, excluding the terminating NUL
* or -1 if this amount would have exceeded b64Max.
*/
int mpw_base64_encode(char *b64Text, size_t b64Max, const uint8_t *plainBuf, size_t plainSize);

View File

@ -157,16 +157,22 @@ const char *mpw_encrypt_v0(
MPMasterKey masterKey, const char *plainText) { MPMasterKey masterKey, const char *plainText) {
// Encrypt // Encrypt
dbg( "-- encrypting plainText: %s\n", plainText );
size_t bufSize = strlen( plainText ); size_t bufSize = strlen( plainText );
const uint8_t *cipherBuf = mpw_aes_encrypt( masterKey, MPMasterKeySize, (const uint8_t *)plainText, bufSize ); const uint8_t *cipherBuf = mpw_aes_encrypt( masterKey, MPMasterKeySize, (const uint8_t *)plainText, bufSize );
dbg( "-- cipherBuf: %lu bytes = ", bufSize ); if (!cipherBuf) {
printb( cipherBuf, bufSize ); err( "AES encryption error: %s\n", strerror( errno ) );
return NULL;
}
// Base64-encode // Base64-encode
char *cipherText = calloc( 1, Base64encode_len( bufSize ) + 1 ); size_t b64Max = mpw_base64_encode_max( bufSize );
Base64encode( cipherText, cipherBuf, bufSize ); char *cipherText = calloc( 1, b64Max + 1 );
dbg( "-- b64 encoded -> cipherText: %s\n", cipherText ); if (mpw_base64_encode( cipherText, b64Max, cipherBuf, bufSize ) < 0) {
err( "Base64 encoding error." );
mpw_free_string( cipherText );
cipherText = NULL;
}
mpw_free( cipherBuf, bufSize ); mpw_free( cipherBuf, bufSize );
return cipherText; return cipherText;
@ -176,17 +182,19 @@ const char *mpw_decrypt_v0(
MPMasterKey masterKey, const char *cipherText) { MPMasterKey masterKey, const char *cipherText) {
// Base64-decode // Base64-decode
dbg( "-- decrypting cipherText: %s\n", cipherText ); size_t bufSize = mpw_base64_decode_max( cipherText );
size_t bufSize = Base64decode_len( cipherText ) + 1;
uint8_t *cipherBuf = calloc( 1, bufSize ); uint8_t *cipherBuf = calloc( 1, bufSize );
Base64decode( cipherBuf, cipherText ); if ((bufSize = (size_t)mpw_base64_decode( cipherBuf, bufSize, cipherText )) < 0) {
dbg( "-- b64 decoded: %lu bytes = ", bufSize ); err( "Base64 decoding error." );
printb( cipherBuf, bufSize ); mpw_free( cipherBuf, mpw_base64_decode_max( cipherText ) );
return NULL;
}
// Decrypt // Decrypt
const char *plainText = (const char *)mpw_aes_decrypt( masterKey, MPMasterKeySize, cipherBuf, bufSize ); const char *plainText = (const char *)mpw_aes_decrypt( masterKey, MPMasterKeySize, cipherBuf, bufSize );
dbg( "-- decrypted -> plainText: %s\n", plainText ); if (!plainText)
err( "AES decryption error: %s\n", strerror( errno ) );
mpw_free( cipherBuf, bufSize ); mpw_free( cipherBuf, bufSize );
return plainText; return plainText;

View File

@ -185,19 +185,22 @@ static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t key
if (!key || keySize < crypto_stream_KEYBYTES) if (!key || keySize < crypto_stream_KEYBYTES)
return NULL; return NULL;
uint8_t cipherKey[crypto_stream_KEYBYTES];
memcpy( cipherKey, key, sizeof( cipherKey ) );
uint8_t nonce[crypto_stream_NONCEBYTES]; uint8_t nonce[crypto_stream_NONCEBYTES];
bzero( (void *)nonce, sizeof( nonce ) ); bzero( (void *)nonce, sizeof( nonce ) );
if (encrypt) { if (encrypt) {
uint8_t *const cipherBuf = malloc( bufSize ); uint8_t *const cipherBuf = malloc( bufSize );
crypto_stream_aes128ctr_xor( cipherBuf, buf, bufSize, nonce, cipherKey ); if (crypto_stream_aes128ctr_xor( cipherBuf, buf, bufSize, nonce, key ) != 0) {
mpw_free( cipherBuf, bufSize );
return NULL;
}
return cipherBuf; return cipherBuf;
} else { } else {
uint8_t *const plainBuf = malloc( bufSize ); uint8_t *const plainBuf = malloc( bufSize );
crypto_stream_aes128ctr( plainBuf, bufSize, nonce, cipherKey ); if (crypto_stream_aes128ctr( plainBuf, bufSize, nonce, key ) != 0) {
mpw_free( plainBuf, bufSize );
return NULL;
}
for (size_t c = 0; c < bufSize; ++c) for (size_t c = 0; c < bufSize; ++c)
plainBuf[c] = buf[c] ^ plainBuf[c]; plainBuf[c] = buf[c] ^ plainBuf[c];
return plainBuf; return plainBuf;