mirror of
https://github.com/Wack0/twltool.git
synced 2025-06-18 17:05:43 -04:00
Wulfystylz release 1.6
This commit is contained in:
commit
3728e20792
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.exe
|
||||
*.o
|
14
Makefile
Normal file
14
Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
OBJS = dsi.o main.o f_xy.o utils.o
|
||||
POLAR_OBJS = polarssl/aes.o polarssl/bignum.o polarssl/rsa.o polarssl/sha2.o sha1.o
|
||||
LIBS = -static-libstdc++ -static
|
||||
CXXFLAGS = -I.
|
||||
CFLAGS = -Wall -Wno-unused-variable -Wno-unused-but-set-variable -I.
|
||||
OUTPUT = twltool
|
||||
CC = gcc
|
||||
|
||||
main: $(OBJS) $(POLAR_OBJS) $(TINYXML_OBJS)
|
||||
g++ -Os -o $(OUTPUT) $(LIBS) $(OBJS) $(POLAR_OBJS) $(TINYXML_OBJS)
|
||||
|
||||
|
||||
clean:
|
||||
rm -rf $(OUTPUT) $(OBJS) $(POLAR_OBJS) $(TINYXML_OBJS)
|
373
dsi.c
Normal file
373
dsi.c
Normal file
@ -0,0 +1,373 @@
|
||||
#include "dsi.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
void dsi_set_key( dsi_context* ctx,
|
||||
unsigned char key[16] )
|
||||
{
|
||||
int i;
|
||||
unsigned char keyswap[16];
|
||||
|
||||
for(i=0; i<16; i++)
|
||||
keyswap[i] = key[15-i];
|
||||
|
||||
aes_setkey_enc(&ctx->aes, keyswap, 128);
|
||||
}
|
||||
|
||||
void dsi_add_ctr( dsi_context* ctx,
|
||||
unsigned int carry)
|
||||
{
|
||||
unsigned int counter[4];
|
||||
unsigned char *outctr = (unsigned char*)ctx->ctr;
|
||||
int sum;
|
||||
signed int i;
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
counter[i] = (outctr[i * 4 + 0] << 24) | (outctr[i * 4 + 1] << 16) |
|
||||
(outctr[i * 4 + 2] << 8) | (outctr[i * 4 + 3] << 0);
|
||||
|
||||
for(i = 3; i >= 0; i--)
|
||||
{
|
||||
sum = counter[i] + carry;
|
||||
|
||||
if (sum < counter[i])
|
||||
carry = 1;
|
||||
else
|
||||
carry = 0;
|
||||
|
||||
counter[i] = sum;
|
||||
}
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
outctr[i * 4 + 0] = counter[i] >> 24;
|
||||
outctr[i * 4 + 1] = counter[i] >> 16;
|
||||
outctr[i * 4 + 2] = counter[i] >> 8;
|
||||
outctr[i * 4 + 3] = counter[i] >> 0;
|
||||
}
|
||||
}
|
||||
|
||||
void dsi_set_ctr( dsi_context* ctx,
|
||||
unsigned char ctr[16] )
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<16; i++)
|
||||
ctx->ctr[i] = ctr[15-i];
|
||||
}
|
||||
|
||||
void dsi_init_ctr( dsi_context* ctx,
|
||||
unsigned char key[16],
|
||||
unsigned char ctr[12] )
|
||||
{
|
||||
dsi_set_key(ctx, key);
|
||||
dsi_set_ctr(ctx, ctr);
|
||||
}
|
||||
|
||||
void dsi_crypt_ctr( dsi_context* ctx,
|
||||
void* in,
|
||||
void* out,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
for(i = 0; i < len; i += 0x10)
|
||||
dsi_crypt_ctr_block(ctx, in+i, out+i);
|
||||
}
|
||||
|
||||
void dsi_crypt_ctr_block( dsi_context* ctx,
|
||||
unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int i;
|
||||
unsigned char stream[16];
|
||||
|
||||
|
||||
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->ctr, stream);
|
||||
|
||||
|
||||
if (input)
|
||||
{
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
output[i] = stream[15-i] ^ input[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0; i<16; i++)
|
||||
output[i] = stream[15-i];
|
||||
}
|
||||
|
||||
dsi_add_ctr(ctx, 1);
|
||||
}
|
||||
|
||||
|
||||
void dsi_init_ccm( dsi_context* ctx,
|
||||
unsigned char key[16],
|
||||
unsigned int maclength,
|
||||
unsigned int payloadlength,
|
||||
unsigned int assoclength,
|
||||
unsigned char nonce[12] )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
|
||||
dsi_set_key(ctx, key);
|
||||
|
||||
ctx->maclen = maclength;
|
||||
|
||||
maclength = (maclength-2)/2;
|
||||
|
||||
payloadlength = (payloadlength+15) & ~15;
|
||||
|
||||
// CCM B0 block:
|
||||
// [1-byte flags] [12-byte nonce] [3-byte size]
|
||||
ctx->mac[0] = (maclength<<3) | 2;
|
||||
if (assoclength)
|
||||
ctx->mac[0] |= (1<<6);
|
||||
for(i=0; i<12; i++)
|
||||
ctx->mac[1+i] = nonce[11-i];
|
||||
ctx->mac[13] = payloadlength>>16;
|
||||
ctx->mac[14] = payloadlength>>8;
|
||||
ctx->mac[15] = payloadlength>>0;
|
||||
|
||||
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->mac, ctx->mac);
|
||||
|
||||
// CCM CTR:
|
||||
// [1-byte flags] [12-byte nonce] [3-byte ctr]
|
||||
ctx->ctr[0] = 2;
|
||||
for(i=0; i<12; i++)
|
||||
ctx->ctr[1+i] = nonce[11-i];
|
||||
ctx->ctr[13] = 0;
|
||||
ctx->ctr[14] = 0;
|
||||
ctx->ctr[15] = 0;
|
||||
|
||||
dsi_crypt_ctr_block(ctx, 0, ctx->S0);
|
||||
}
|
||||
|
||||
void dsi_encrypt_ccm_block( dsi_context* ctx,
|
||||
unsigned char input[16],
|
||||
unsigned char output[16],
|
||||
unsigned char* mac )
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<16; i++)
|
||||
ctx->mac[i] ^= input[15-i];
|
||||
|
||||
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->mac, ctx->mac);
|
||||
|
||||
if (mac)
|
||||
{
|
||||
for(i=0; i<16; i++)
|
||||
mac[i] = ctx->mac[15-i] ^ ctx->S0[i];
|
||||
}
|
||||
|
||||
if (output)
|
||||
dsi_crypt_ctr_block(ctx, input, output);
|
||||
}
|
||||
|
||||
|
||||
void dsi_decrypt_ccm_block( dsi_context* ctx,
|
||||
unsigned char input[16],
|
||||
unsigned char output[16],
|
||||
unsigned char* mac )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
if (output)
|
||||
{
|
||||
dsi_crypt_ctr_block(ctx, input, output);
|
||||
|
||||
|
||||
for(i=0; i<16; i++)
|
||||
ctx->mac[i] ^= output[15-i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0; i<16; i++)
|
||||
ctx->mac[i] ^= input[15-i];
|
||||
}
|
||||
|
||||
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->mac, ctx->mac);
|
||||
|
||||
|
||||
if (mac)
|
||||
{
|
||||
for(i=0; i<16; i++)
|
||||
mac[i] = ctx->mac[15-i] ^ ctx->S0[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dsi_decrypt_ccm( dsi_context* ctx,
|
||||
unsigned char* input,
|
||||
unsigned char* output,
|
||||
unsigned int size,
|
||||
unsigned char* mac )
|
||||
{
|
||||
unsigned char block[16];
|
||||
unsigned char ctr[16];
|
||||
|
||||
while(size > 16)
|
||||
{
|
||||
dsi_decrypt_ccm_block(ctx, input, output, mac);
|
||||
|
||||
if (input)
|
||||
input += 16;
|
||||
if (output)
|
||||
output += 16;
|
||||
|
||||
size -= 16;
|
||||
}
|
||||
|
||||
memcpy(ctr, ctx->ctr, 16);
|
||||
memset(block, 0, 16);
|
||||
dsi_crypt_ctr_block(ctx, block, block);
|
||||
memcpy(ctx->ctr, ctr, 16);
|
||||
memcpy(block, input, size);
|
||||
|
||||
|
||||
dsi_decrypt_ccm_block(ctx, block, block, mac);
|
||||
memcpy(output, block, size);
|
||||
}
|
||||
|
||||
|
||||
void dsi_encrypt_ccm( dsi_context* ctx,
|
||||
unsigned char* input,
|
||||
unsigned char* output,
|
||||
unsigned int size,
|
||||
unsigned char* mac )
|
||||
{
|
||||
unsigned char block[16];
|
||||
|
||||
while(size > 16)
|
||||
{
|
||||
dsi_encrypt_ccm_block(ctx, input, output, mac);
|
||||
|
||||
if (input)
|
||||
input += 16;
|
||||
if (output)
|
||||
output += 16;
|
||||
|
||||
size -= 16;
|
||||
}
|
||||
|
||||
memset(block, 0, 16);
|
||||
memcpy(block, input, size);
|
||||
dsi_encrypt_ccm_block(ctx, block, block, mac);
|
||||
memcpy(output, block, size);
|
||||
}
|
||||
|
||||
void dsi_es_init( dsi_es_context* ctx,
|
||||
unsigned char key[16] )
|
||||
{
|
||||
memcpy(ctx->key, key, 16);
|
||||
ctx->randomnonce = 1;
|
||||
}
|
||||
|
||||
void dsi_es_set_nonce( dsi_es_context* ctx,
|
||||
unsigned char nonce[12] )
|
||||
{
|
||||
memcpy(ctx->nonce, nonce, 12);
|
||||
ctx->randomnonce = 0;
|
||||
}
|
||||
|
||||
void dsi_es_set_random_nonce( dsi_es_context* ctx )
|
||||
{
|
||||
ctx->randomnonce = 1;
|
||||
}
|
||||
|
||||
|
||||
int dsi_es_decrypt( dsi_es_context* ctx,
|
||||
unsigned char* buffer,
|
||||
unsigned char metablock[32],
|
||||
unsigned int size )
|
||||
{
|
||||
unsigned char ctr[16];
|
||||
unsigned char nonce[12];
|
||||
unsigned char scratchpad[16];
|
||||
unsigned char chkmac[16];
|
||||
unsigned char genmac[16];
|
||||
dsi_context cryptoctx;
|
||||
unsigned int chksize;
|
||||
|
||||
|
||||
memcpy(chkmac, metablock, 16);
|
||||
|
||||
memcpy(ctr, metablock + 16, 16);
|
||||
ctr[0] = 0;
|
||||
ctr[13] = 0;
|
||||
ctr[14] = 0;
|
||||
ctr[15] = 0;
|
||||
|
||||
dsi_init_ctr(&cryptoctx, ctx->key, ctr);
|
||||
dsi_crypt_ctr_block(&cryptoctx, metablock+16, scratchpad);
|
||||
|
||||
chksize = (scratchpad[13]<<16) | (scratchpad[14]<<8) | (scratchpad[15]<<0);
|
||||
|
||||
if (scratchpad[0] != 0x3A)
|
||||
return -1;
|
||||
|
||||
if(chksize != size)
|
||||
return -2;
|
||||
|
||||
memcpy(nonce, metablock + 17, 12);
|
||||
|
||||
dsi_init_ccm(&cryptoctx, ctx->key, 16, size, 0, nonce);
|
||||
dsi_decrypt_ccm(&cryptoctx, buffer, buffer, size, genmac);
|
||||
|
||||
if (memcmp(genmac, chkmac, 16) != 0)
|
||||
return -3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void dsi_es_encrypt( dsi_es_context* ctx,
|
||||
unsigned char* buffer,
|
||||
unsigned char metablock[32],
|
||||
unsigned int size )
|
||||
{
|
||||
int i;
|
||||
unsigned char nonce[12];
|
||||
unsigned char mac[16];
|
||||
unsigned char ctr[16];
|
||||
unsigned char scratchpad[16];
|
||||
dsi_context cryptoctx;
|
||||
|
||||
if (ctx->randomnonce)
|
||||
{
|
||||
srand( (unsigned int)time(0) );
|
||||
|
||||
for(i=0; i<12; i++)
|
||||
nonce[i] = rand();
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(nonce, ctx->nonce, 12);
|
||||
}
|
||||
|
||||
dsi_init_ccm(&cryptoctx, ctx->key, 16, size, 0, nonce);
|
||||
dsi_encrypt_ccm(&cryptoctx, buffer, buffer, size, mac);
|
||||
|
||||
memset(scratchpad, 0, 16);
|
||||
scratchpad[0] = 0x3A;
|
||||
scratchpad[13] = size >> 16;
|
||||
scratchpad[14] = size >> 8;
|
||||
scratchpad[15] = size >> 0;
|
||||
|
||||
memset(ctr, 0, 16);
|
||||
memcpy(ctr+1, nonce, 12);
|
||||
|
||||
dsi_init_ctr(&cryptoctx, ctx->key, ctr);
|
||||
dsi_crypt_ctr_block(&cryptoctx, scratchpad, metablock+16);
|
||||
memcpy(metablock+17, nonce, 12);
|
||||
|
||||
memcpy(metablock, mac, 16);
|
||||
|
||||
}
|
104
dsi.h
Normal file
104
dsi.h
Normal file
@ -0,0 +1,104 @@
|
||||
#ifndef _DSI_H_
|
||||
#define _DSI_H_
|
||||
|
||||
#include "polarssl\aes.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char ctr[16];
|
||||
unsigned char mac[16];
|
||||
unsigned char S0[16];
|
||||
unsigned int maclen;
|
||||
|
||||
aes_context aes;
|
||||
}
|
||||
dsi_context;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char key[16];
|
||||
unsigned char nonce[12];
|
||||
int randomnonce;
|
||||
} dsi_es_context;
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void dsi_set_key( dsi_context* ctx,
|
||||
unsigned char key[16] );
|
||||
|
||||
void dsi_add_ctr( dsi_context* ctx,
|
||||
unsigned int carry );
|
||||
|
||||
void dsi_set_ctr( dsi_context* ctx,
|
||||
unsigned char ctr[16] );
|
||||
|
||||
void dsi_init_ctr( dsi_context* ctx,
|
||||
unsigned char key[16],
|
||||
unsigned char ctr[12] );
|
||||
|
||||
void dsi_crypt_ctr( dsi_context* ctx,
|
||||
void* in,
|
||||
void* out,
|
||||
unsigned int len);
|
||||
|
||||
void dsi_crypt_ctr_block( dsi_context* ctx,
|
||||
unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
void dsi_init_ccm( dsi_context* ctx,
|
||||
unsigned char key[16],
|
||||
unsigned int maclength,
|
||||
unsigned int payloadlength,
|
||||
unsigned int assoclength,
|
||||
unsigned char nonce[12] );
|
||||
|
||||
void dsi_encrypt_ccm_block( dsi_context* ctx,
|
||||
unsigned char input[16],
|
||||
unsigned char output[16],
|
||||
unsigned char* mac );
|
||||
|
||||
void dsi_decrypt_ccm_block( dsi_context* ctx,
|
||||
unsigned char input[16],
|
||||
unsigned char output[16],
|
||||
unsigned char* mac );
|
||||
|
||||
|
||||
void dsi_decrypt_ccm( dsi_context* ctx,
|
||||
unsigned char* input,
|
||||
unsigned char* output,
|
||||
unsigned int size,
|
||||
unsigned char* mac );
|
||||
|
||||
void dsi_encrypt_ccm( dsi_context* ctx,
|
||||
unsigned char* input,
|
||||
unsigned char* output,
|
||||
unsigned int size,
|
||||
unsigned char* mac );
|
||||
|
||||
void dsi_es_init( dsi_es_context* ctx,
|
||||
unsigned char key[16] );
|
||||
|
||||
void dsi_es_set_nonce( dsi_es_context* ctx,
|
||||
unsigned char nonce[12] );
|
||||
|
||||
void dsi_es_set_random_nonce( dsi_es_context* ctx );
|
||||
|
||||
int dsi_es_decrypt( dsi_es_context* ctx,
|
||||
unsigned char* buffer,
|
||||
unsigned char metablock[32],
|
||||
unsigned int size );
|
||||
|
||||
void dsi_es_encrypt( dsi_es_context* ctx,
|
||||
unsigned char* buffer,
|
||||
unsigned char metablock[32],
|
||||
unsigned int size );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _DSI_H_
|
199
f_xy.c
Normal file
199
f_xy.c
Normal file
@ -0,0 +1,199 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <stdint.h>
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
// flip each word and return as a u64 array
|
||||
void aes_flip_to_64(u32 *in, u64* out)
|
||||
{
|
||||
u32 endian_flip[4];
|
||||
u32 i;
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
endian_flip[i] = getbe32((u8*)&in[i]);
|
||||
|
||||
out[0] = (u64)endian_flip[1] | ((u64)endian_flip[0] << 32);
|
||||
out[1] = (u64)endian_flip[3] | ((u64)endian_flip[2] << 32);
|
||||
}
|
||||
|
||||
void aes_unflip_to_32(u64* in, u32* out)
|
||||
{
|
||||
out[0] = getbe32((u8*)&in[0]+4);
|
||||
out[1] = getbe32((u8*)&in[0]);
|
||||
out[2] = getbe32((u8*)&in[1]+4);
|
||||
out[3] = getbe32((u8*)&in[1]);
|
||||
}
|
||||
|
||||
void n128_lrot_3ds_internal(u32 *num, u32 shift)
|
||||
{
|
||||
u64 tmp[2];
|
||||
u64 num_work[2];
|
||||
|
||||
aes_flip_to_64(num, num_work);
|
||||
|
||||
tmp[0] = num_work[0]<<shift;
|
||||
tmp[1] = num_work[1]<<shift;
|
||||
tmp[0] |= num_work[1]>>(64-shift);
|
||||
tmp[1] |= num_work[0]>>(64-shift);
|
||||
|
||||
aes_unflip_to_32(tmp, num);
|
||||
}
|
||||
|
||||
void n128_rrot_3ds_internal(u32 *num, u32 shift)
|
||||
{
|
||||
u64 tmp[2];
|
||||
u64 num_work[2];
|
||||
|
||||
aes_flip_to_64(num, num_work);
|
||||
|
||||
tmp[0] = num_work[0]>>shift;
|
||||
tmp[1] = num_work[1]>>shift;
|
||||
tmp[0] |= (num_work[1]<<(64-shift));
|
||||
tmp[1] |= (num_work[0]<<(64-shift));
|
||||
|
||||
aes_unflip_to_32(tmp, num);
|
||||
}
|
||||
|
||||
void n128_lrot_3ds(u32 *num, u32 shift)
|
||||
{
|
||||
u32 shift_cycle;
|
||||
while(shift > 0)
|
||||
{
|
||||
if(shift >= 32)
|
||||
{
|
||||
shift_cycle = 32;
|
||||
shift -= 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
shift_cycle = shift;
|
||||
shift = 0;
|
||||
}
|
||||
n128_lrot_3ds_internal(num, shift_cycle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void n128_rrot_3ds(u32 *num, u32 shift)
|
||||
{
|
||||
u32 shift_cycle;
|
||||
while(shift > 0)
|
||||
{
|
||||
if(shift >= 32)
|
||||
{
|
||||
shift_cycle = 32;
|
||||
shift -= 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
shift_cycle = shift;
|
||||
shift = 0;
|
||||
}
|
||||
n128_rrot_3ds_internal(num, shift_cycle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void n128_add_3ds(u32 *a, u32 *b)
|
||||
{
|
||||
u64 a64[4];
|
||||
u64 b64[4];
|
||||
aes_flip_to_64(a, a64);
|
||||
aes_flip_to_64(b, b64);
|
||||
|
||||
uint64_t tmp = (a64[0]>>1)+(b64[0]>>1) + (a64[0] & b64[0] & 1);
|
||||
|
||||
tmp = tmp >> 63;
|
||||
a64[0] = a64[0] + b64[0];
|
||||
a64[1] = a64[1] + b64[1] + tmp;
|
||||
aes_unflip_to_32(a64, a);
|
||||
}
|
||||
|
||||
void n128_lrot(uint64_t *num, uint32_t shift)
|
||||
{
|
||||
uint64_t tmp[2];
|
||||
|
||||
tmp[0] = num[0]<<shift;
|
||||
tmp[1] = num[1]<<shift;
|
||||
tmp[0] |= (num[1]>>(64-shift));
|
||||
tmp[1] |= (num[0]>>(64-shift));
|
||||
|
||||
num[0] = tmp[0];
|
||||
num[1] = tmp[1];
|
||||
}
|
||||
|
||||
void n128_rrot(uint64_t *num, uint32_t shift)
|
||||
{
|
||||
uint64_t tmp[2];
|
||||
|
||||
tmp[0] = num[0]>>shift;
|
||||
tmp[1] = num[1]>>shift;
|
||||
tmp[0] |= (num[1]<<(64-shift));
|
||||
tmp[1] |= (num[0]<<(64-shift));
|
||||
|
||||
num[0] = tmp[0];
|
||||
num[1] = tmp[1];
|
||||
}
|
||||
|
||||
void n128_add(uint64_t *a, uint64_t *b)
|
||||
{
|
||||
uint64_t *a64 = a;
|
||||
uint64_t *b64 = b;
|
||||
uint64_t tmp = (a64[0]>>1)+(b64[0]>>1) + (a64[0] & b64[0] & 1);
|
||||
|
||||
tmp = tmp >> 63;
|
||||
a64[0] = a64[0] + b64[0];
|
||||
a64[1] = a64[1] + b64[1] + tmp;
|
||||
}
|
||||
|
||||
void n128_sub(uint64_t *a, uint64_t *b)
|
||||
{
|
||||
uint64_t *a64 = a;
|
||||
uint64_t *b64 = b;
|
||||
uint64_t tmp = (a64[0]>>1)-(b64[0]>>1) - ((a64[0]>>63) & (b64[0]>>63) & 1);
|
||||
|
||||
tmp = tmp >> 63;
|
||||
a64[0] = a64[0] - b64[0];
|
||||
a64[1] = a64[1] - b64[1] - tmp;
|
||||
}
|
||||
|
||||
void F_XY(uint32_t *key, uint32_t *key_x, uint32_t *key_y)
|
||||
{
|
||||
int i;
|
||||
unsigned char key_xy[16];
|
||||
|
||||
memset(key_xy, 0, 16);
|
||||
memset(key, 0, 16);
|
||||
for(i=0; i<16; i++)key_xy[i] = ((unsigned char*)key_x)[i] ^ ((unsigned char*)key_y)[i];
|
||||
|
||||
key[0] = 0x1a4f3e79;
|
||||
key[1] = 0x2a680f5f;
|
||||
key[2] = 0x29590258;
|
||||
key[3] = 0xfffefb4e;
|
||||
|
||||
n128_add((uint64_t*)key, (uint64_t*)key_xy);
|
||||
n128_lrot((uint64_t*)key, 42);
|
||||
}
|
||||
|
||||
//F_XY_reverse does the reverse of F(X^Y): takes (normal)key, and does F in reverse to generate the original X^Y key_xy.
|
||||
void F_XY_reverse(uint32_t *key, uint32_t *key_xy)
|
||||
{
|
||||
uint32_t tmpkey[4];
|
||||
memset(key_xy, 0, 16);
|
||||
memset(tmpkey, 0, 16);
|
||||
memcpy(tmpkey, key, 16);
|
||||
|
||||
key_xy[0] = 0x1a4f3e79;
|
||||
key_xy[1] = 0x2a680f5f;
|
||||
key_xy[2] = 0x29590258;
|
||||
key_xy[3] = 0xfffefb4e;
|
||||
|
||||
n128_rrot((uint64_t*)tmpkey, 42);
|
||||
n128_sub((uint64_t*)tmpkey, (uint64_t*)key_xy);
|
||||
memcpy(key_xy, tmpkey, 16);
|
||||
}
|
||||
|
20
f_xy.h
Normal file
20
f_xy.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _H_F_XY
|
||||
#define _H_F_XY
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void F_XY(uint32_t *key, uint32_t *key_x, uint32_t *key_y);
|
||||
void F_XY_reverse(uint32_t *key, uint32_t *key_xy);
|
||||
|
||||
void n128_lrot_3ds(u32 *num, u32 shift);
|
||||
void n128_rrot_3ds(u32 *num, u32 shift);
|
||||
void n128_add_3ds(u32 *a, u32 *b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
789
main.c
Normal file
789
main.c
Normal file
@ -0,0 +1,789 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include "utils.h"
|
||||
#include "f_xy.h"
|
||||
#include "dsi.h"
|
||||
#include <sys\timeb.h>
|
||||
#include "sha1.h"
|
||||
|
||||
u32 tadsrl_keyX[4] = {0x4E00004A, 0x4A00004E, 0, 0};
|
||||
u8 tadsrl_keyY[16] = {0xcc, 0xfc, 0xa7, 0x03, 0x20, 0x61, 0xbe, 0x84, 0xd3, 0xeb, 0xa4, 0x26, 0xb8, 0x6d, 0xbe, 0xc2};
|
||||
u8 sd_key[16] = {0x3d, 0xa3, 0xea, 0x33, 0x4c, 0x86, 0xa6, 0xb0, 0x2a, 0xae, 0xdb, 0x51, 0x16, 0xea, 0x92, 0x62};
|
||||
char modcrypt_shared_key[8] = {'N','i','n','t','e','n','d','o'};
|
||||
// middle two words are 'NINTENDO' big endian
|
||||
u32 emmc_keyX_3DS[4] = {0x00000000, 0x544E494E, 0x4F444E45, 0x00000000};
|
||||
u32 emmc_keyY[4] = {0x0AB9DC76,0xBD4DC4D3,0x202DDD1D,0xE1A00005};
|
||||
u8 block[0x10];
|
||||
int i;
|
||||
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
u8 status;
|
||||
u8 start_chs[3];
|
||||
u8 partition_type;
|
||||
u8 end_chs[3];
|
||||
u32 start_sector;
|
||||
u32 num_sectors;
|
||||
} mbr_partition;
|
||||
|
||||
// laaaaazy!
|
||||
typedef struct
|
||||
{
|
||||
u8 code[446];
|
||||
mbr_partition partition[4];
|
||||
u8 signature[2];
|
||||
} mbr;
|
||||
|
||||
void decrypt_modcrypt_area(dsi_context* ctx, u8 *buffer, unsigned int size)
|
||||
{
|
||||
uint32_t len = size / 0x10;
|
||||
while(len>0)
|
||||
{
|
||||
memset(block, 0, 0x10);
|
||||
dsi_crypt_ctr_block(ctx, buffer, block);
|
||||
memcpy(buffer, block, 0x10);
|
||||
buffer+=0x10;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
// From dsi_srl_extract
|
||||
int decryptsrl(u8 *srl)
|
||||
{
|
||||
u8 *keyX_ptr = NULL, *keyY_ptr = NULL;
|
||||
uint32_t offset, size;
|
||||
int verbose=0;
|
||||
u8 *header, *buffer;
|
||||
u8 key_x[16];
|
||||
u8 key_y[16];
|
||||
u8 key[16];
|
||||
dsi_context ctx;
|
||||
|
||||
header = srl;
|
||||
|
||||
memcpy(key_x, modcrypt_shared_key, 8);
|
||||
|
||||
memcpy(&key_x[8], &header[0x0c], 4);
|
||||
key_x[12 + 0] = header[0x0c + 3];
|
||||
key_x[12 + 1] = header[0x0c + 2];
|
||||
key_x[12 + 2] = header[0x0c + 1];
|
||||
key_x[12 + 3] = header[0x0c + 0];
|
||||
memcpy(key_y, &header[0x350], 16);
|
||||
|
||||
if((header[0x1c] & 4) || (header[0x1bf] & 0x80))
|
||||
{
|
||||
printf("Crypting dev modcrypt.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Crypting retail modcrypt.\n");
|
||||
keyX_ptr = key_x;
|
||||
keyY_ptr = key_y;
|
||||
}
|
||||
memcpy(key, header, 16);
|
||||
|
||||
printf("Crypting...\n");
|
||||
if(keyX_ptr)
|
||||
{
|
||||
F_XY((uint32_t*)key, (uint32_t*)key_x, (uint32_t*)key_y);
|
||||
}
|
||||
dsi_set_key(&ctx, key);
|
||||
|
||||
|
||||
memcpy(&offset, &header[0x220], 4);
|
||||
memcpy(&size, &header[0x224], 4);
|
||||
dsi_set_ctr(&ctx, &header[0x300]);
|
||||
|
||||
if(offset!=0)
|
||||
{
|
||||
printf("Modcrypt area 0: offset %x size %x\n", offset, size);
|
||||
buffer = srl + offset;
|
||||
decrypt_modcrypt_area(&ctx, buffer, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Modcrypt area 0 is unused.\n");
|
||||
}
|
||||
|
||||
|
||||
memcpy(&offset, &header[0x228], 4);
|
||||
memcpy(&size, &header[0x22c], 4);
|
||||
dsi_set_ctr(&ctx, &header[0x314]);
|
||||
|
||||
if(offset!=0)
|
||||
{
|
||||
printf("Modcrypt area 1: offset %x size %x\n", offset, size);
|
||||
buffer = srl + offset;
|
||||
decrypt_modcrypt_area(&ctx, buffer, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Modcrypt area 1 is unused.\n");
|
||||
}
|
||||
|
||||
printf("Done.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void decrypt_boot2_section(u8* data, u32 len, bool is3DS)
|
||||
{
|
||||
u8 normalkey[16] = {0};
|
||||
u8 keyX_TWLFIRM[16] = {0xE1, 0xEB, 0xDF, 0x44, 0xAB, 0x1D, 0x81, 0xE3, 0x93, 0x9A, 0x4A, 0xB5, 0x36, 0xFC, 0x3A, 0x0E};
|
||||
u8 keyX_DSi[16] = {0x4E, 0x69, 0x6E, 0x74, 0x65, 0x6E, 0x64, 0x6F, 0x20, 0x44, 0x53, 0x00, 0x01, 0x23, 0x21, 0x00};
|
||||
u8 keyY_3DS[16] = {0xAB, 0x4E, 0x18, 0xA8, 0x51, 0x16, 0x90, 0x7E, 0x9F, 0x65, 0xF0, 0xCE, 0x21, 0x7C, 0x3A, 0x70};
|
||||
u8 keyY_DSi[16] = {0xEC, 0x07, 0x00, 0x00, 0x34, 0xE2, 0x94, 0x7C, 0xC3, 0x0E, 0x81, 0x7C, 0xEC, 0x07, 0x00, 0x00};
|
||||
u32 ctr[4];
|
||||
memset(ctr, 0, 16);
|
||||
|
||||
int i;
|
||||
|
||||
dsi_context dsictx;
|
||||
if(is3DS == true)
|
||||
F_XY((u32*) normalkey, (u32*)keyX_TWLFIRM, (u32*)keyY_3DS);
|
||||
else
|
||||
F_XY((u32*) normalkey, (u32*)keyX_DSi, (u32*)keyY_DSi);
|
||||
|
||||
ctr[0] = len;
|
||||
ctr[1] = -len;
|
||||
ctr[2] = ~len;
|
||||
printf("CTR:\n");
|
||||
hexdump(ctr,16);
|
||||
|
||||
printf("Normalkey:\n");
|
||||
hexdump(normalkey,16);
|
||||
dsi_set_key(&dsictx, normalkey);
|
||||
dsi_set_ctr(&dsictx, (u8*)ctr);
|
||||
|
||||
// auto-increments ctr
|
||||
for(i = 0; i < len; i+= 0x10)
|
||||
dsi_crypt_ctr_block(&dsictx, data+i, data+i);
|
||||
}
|
||||
|
||||
void decrypt_boot2(char* in, bool is3DS)
|
||||
{
|
||||
u32 offset;
|
||||
u32 len;
|
||||
u8* data;
|
||||
FILE* f_in = fopen(in,"r+b");
|
||||
FILE* f_out;
|
||||
if(f_in == NULL)
|
||||
{
|
||||
printf("Input filename invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
// decrypt and write ARM9
|
||||
f_out = fopen("arm9.bin","wb");
|
||||
fseek(f_in, 0x220, SEEK_SET);
|
||||
fread(&offset, 1, sizeof(offset), f_in);
|
||||
fseek(f_in, 0x22C, SEEK_SET);
|
||||
fread(&len, 1, sizeof(len), f_in);
|
||||
|
||||
fseek(f_in, offset, SEEK_SET);
|
||||
data = malloc(len);
|
||||
fread(data, 1, len, f_in);
|
||||
decrypt_boot2_section(data, len, is3DS);
|
||||
fwrite(data, 1, len, f_out);
|
||||
free(data);
|
||||
fclose(f_out);
|
||||
|
||||
// decrypt and write ARM7
|
||||
f_out = fopen("arm7.bin","wb");
|
||||
fseek(f_in, 0x230, SEEK_SET);
|
||||
fread(&offset, 1, sizeof(offset), f_in);
|
||||
fseek(f_in, 0x23C, SEEK_SET);
|
||||
fread(&len, 1, sizeof(len), f_in);
|
||||
|
||||
fseek(f_in, offset, SEEK_SET);
|
||||
data = malloc(len);
|
||||
fread(data, 1, len, f_in);
|
||||
decrypt_boot2_section(data, len, is3DS);
|
||||
fwrite(data, 1, len, f_out);
|
||||
fclose(f_out);
|
||||
fclose(f_in);
|
||||
free(data);
|
||||
|
||||
}
|
||||
|
||||
void decrypt_srl(char* in, char* out)
|
||||
{
|
||||
FILE* f_in = fopen(in,"r+b");
|
||||
FILE* f_out;
|
||||
if(!strcmp(in,out))
|
||||
f_out = fopen(out,"r+b");
|
||||
else
|
||||
f_out = fopen(out,"wb");
|
||||
if(f_in == NULL)
|
||||
{
|
||||
printf("Input filename invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
fseek(f_in, 0L, SEEK_END);
|
||||
u32 fsize = ftell(f_in);
|
||||
fseek(f_in, 0L, SEEK_SET);
|
||||
u8* srl = malloc(fsize);
|
||||
fread(srl, 1, fsize, f_in);
|
||||
|
||||
decryptsrl(srl);
|
||||
|
||||
fwrite(srl, 1, fsize, f_out);
|
||||
free(srl);
|
||||
fclose(f_in);
|
||||
fclose(f_out);
|
||||
}
|
||||
|
||||
void cid_brute_3ds(u32* consoleID, u8* emmc_cid, u8* test_data, char* cidfile, bool isN3DS)
|
||||
{
|
||||
dsi_context ctx;
|
||||
int i, diff;
|
||||
struct timeb start, end;
|
||||
u8 emmc_normalkey[16];
|
||||
u8 emmc_cid_hash[20];
|
||||
u8 CTR[16];
|
||||
|
||||
u8* consoleID8 = (u8*)consoleID;
|
||||
|
||||
if(isN3DS == true)
|
||||
consoleID[1] = 0x00000002;
|
||||
else
|
||||
consoleID[1] = 0x00000000;
|
||||
emmc_keyX_3DS[3] = consoleID[1] ^ 0x08C267B7;
|
||||
|
||||
|
||||
u8 target_bytes[16] = {0};
|
||||
sha1(emmc_cid_hash, emmc_cid, 16);
|
||||
memcpy(CTR, emmc_cid_hash, 16);
|
||||
|
||||
// store our target ctr so we won't have to copy + increment it every iteration
|
||||
dsi_set_ctr(&ctx, (u8*)CTR);
|
||||
dsi_add_ctr(&ctx, 0x1E);
|
||||
memcpy(CTR, ctx.ctr, 16);
|
||||
|
||||
ftime(&start);
|
||||
|
||||
// first bit is always set, we only need to brute the bottom 7 bits
|
||||
for(i = 0x00000000; i < 0x7FFFFFFF; i++)
|
||||
{
|
||||
consoleID[0] = i;
|
||||
|
||||
memcpy(ctx.ctr, CTR, 16);
|
||||
emmc_keyX_3DS[0] = (consoleID[0] ^ 0xB358A6AF) | 0x80000000;
|
||||
F_XY((u32*)emmc_normalkey, (u32*) emmc_keyX_3DS, (u32*) emmc_keyY);
|
||||
dsi_set_key(&ctx, emmc_normalkey);
|
||||
|
||||
dsi_crypt_ctr_block(&ctx, test_data, block);
|
||||
|
||||
// if this block decrypts to all zero, we've got the right consoleID.
|
||||
if(!memcmp(target_bytes, block, sizeof(target_bytes))){
|
||||
// print this as-is without endian flipping!
|
||||
printf("Got it!! ConsoleID is ");
|
||||
for(i = 0; i < 8; i++)
|
||||
printf("%02X", consoleID8[i]);
|
||||
printf("\n");
|
||||
|
||||
if(cidfile)
|
||||
{
|
||||
FILE* f = fopen(cidfile, "w+b");
|
||||
if(!f)
|
||||
{
|
||||
printf("Failed to write CID to %s! Continuing...\n", cidfile);
|
||||
return;
|
||||
}
|
||||
fwrite(consoleID, 1, sizeof(consoleID), f);
|
||||
fclose(f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(!(i % 0x200000))
|
||||
printf("CID 0x%08X of 0x7FFFFFFF\n",i);
|
||||
}
|
||||
ftime(&end);
|
||||
diff = (int) (1000.0 * (end.time - start.time)
|
||||
+ (end.millitm - start.millitm));
|
||||
printf("Bruteforce took %u milliseconds\n", diff);
|
||||
}
|
||||
|
||||
void nand_decrypt_3ds(u8 *emmc_cid, u32 *consoleID, char *in, char *out, bool brute_cid, char* cidfile, bool isN3DS)
|
||||
{
|
||||
dsi_context ctx;
|
||||
u32 i;
|
||||
u8 emmc_normalkey[16];
|
||||
u8 emmc_cid_hash[20];
|
||||
u8 CTR[16];
|
||||
u8 brute_buf[16];
|
||||
|
||||
if(brute_cid == true)
|
||||
{
|
||||
FILE* f_in = fopen(in,"r+b");
|
||||
fseek(f_in, 0x1E0, SEEK_SET);
|
||||
fread(brute_buf, 1, sizeof(brute_buf), f_in);
|
||||
fclose(f_in);
|
||||
cid_brute_3ds(consoleID, emmc_cid, brute_buf, cidfile, isN3DS);
|
||||
}
|
||||
|
||||
// Prepare CTR by SHA1-hashing eMMC CID
|
||||
sha1(emmc_cid_hash, emmc_cid, 16);
|
||||
memcpy(CTR, emmc_cid_hash, 16);
|
||||
dsi_set_ctr(&ctx, (u8*)CTR);
|
||||
|
||||
// Generate AES normalkey from consoleID
|
||||
emmc_keyX_3DS[0] = (consoleID[0] ^ 0xB358A6AF) | 0x80000000;
|
||||
emmc_keyX_3DS[3] = consoleID[1] ^ 0x08C267B7;
|
||||
F_XY((u32*) emmc_normalkey, (u32*) emmc_keyX_3DS, (u32*) emmc_keyY);
|
||||
dsi_set_key(&ctx, emmc_normalkey);
|
||||
|
||||
FILE* f_in = fopen(in,"r+b");
|
||||
FILE* f_out;
|
||||
if(!strcmp(in,out))
|
||||
f_out = fopen(out,"r+b");
|
||||
else
|
||||
f_out = fopen(out,"wb");
|
||||
if(f_in == NULL)
|
||||
{
|
||||
printf("Input filename invalid!");
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < 0x0B100000; i += 0x10)
|
||||
{
|
||||
fread(block, 1, 0x10, f_in);
|
||||
dsi_crypt_ctr_block(&ctx, block, block);
|
||||
fwrite(block, 1, 0x10, f_out);
|
||||
if(i % 0x1000000 == 0)
|
||||
printf("%.2f %% complete.\n",(100.0 * i / 0x0B100000));
|
||||
}
|
||||
fclose(f_in);
|
||||
fclose(f_out);
|
||||
printf("Crypt complete!");
|
||||
}
|
||||
|
||||
void file_copy_append(FILE* f_in, FILE* f_out, dsi_context* ctx, u8 disp_progress, u32 start_addr, u32 end_addr)
|
||||
{
|
||||
u32 cur_size;
|
||||
const u32 buf_size = 0x100000;
|
||||
void* buf = malloc(buf_size);
|
||||
if(!buf)
|
||||
{
|
||||
printf("Failed to allocate %d byte buf for file operation!", buf_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fseek(f_in, start_addr, SEEK_SET);
|
||||
|
||||
for(i = start_addr; i < end_addr; i += buf_size)
|
||||
{
|
||||
cur_size = (end_addr - i) >= buf_size ? buf_size : end_addr - i;
|
||||
fread(buf, 1, cur_size, f_in);
|
||||
|
||||
// do CTR crypto if a ctx is supplied
|
||||
if(ctx)
|
||||
dsi_crypt_ctr(ctx, buf, buf, cur_size);
|
||||
fwrite(buf, 1, cur_size, f_out);
|
||||
|
||||
//update progress every 16MB
|
||||
if(disp_progress && (((i - start_addr) / buf_size) % 25) == 0)
|
||||
printf("%.2f %% complete.\n",100.0 * (i - start_addr) / (end_addr - start_addr));
|
||||
}
|
||||
if(disp_progress)
|
||||
printf("100.00%% complete.\n");
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void nand_decrypt_dsi(u8 *emmc_cid, u32 *consoleID, char *in, char *out)
|
||||
{
|
||||
dsi_context ctx;
|
||||
u32 i;
|
||||
u32 emmc_keyX[4];
|
||||
u8 emmc_normalkey[16];
|
||||
u8 emmc_cid_hash[20];
|
||||
u8 base_ctr[16];
|
||||
mbr mbr;
|
||||
|
||||
// Prepare AES CTR by SHA1-hashing eMMC CID
|
||||
sha1(emmc_cid_hash, emmc_cid, 16);
|
||||
memcpy(base_ctr, emmc_cid_hash, 16);
|
||||
dsi_set_ctr(&ctx, (u8*)base_ctr);
|
||||
|
||||
// Endian-swap the input ConsoleID (provided from tad footer)
|
||||
consoleID[1] = getbe32((u8*)consoleID);
|
||||
consoleID[0] = getbe32((u8*)consoleID+4);
|
||||
|
||||
// Generate AES normalkey from consoleID (which comes in reverse word order)
|
||||
emmc_keyX[0] = consoleID[0];
|
||||
emmc_keyX[1] = consoleID[0] ^ 0x24EE6906;
|
||||
emmc_keyX[2] = consoleID[1] ^ 0xE65B601D;
|
||||
emmc_keyX[3] = consoleID[1];
|
||||
F_XY((u32*) emmc_normalkey, (u32*) emmc_keyX, (u32*) emmc_keyY);
|
||||
dsi_set_key(&ctx, emmc_normalkey);
|
||||
|
||||
FILE* f_in = fopen(in,"r+b");
|
||||
FILE* f_out;
|
||||
if(!strcmp(in,out))
|
||||
f_out = fopen(out,"r+b");
|
||||
else
|
||||
f_out = fopen(out,"wb");
|
||||
if(f_in == NULL)
|
||||
{
|
||||
printf("Input filename invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
// get MBR from encrypted or decrypted NAND
|
||||
fread(&mbr, 1, 0x200, f_in);
|
||||
if(mbr.signature[0] != 0x55 || mbr.signature[1] != 0xAA)
|
||||
{
|
||||
dsi_crypt_ctr(&ctx, &mbr, &mbr, 0x200);
|
||||
if(mbr.signature[0] != 0x55 || mbr.signature[1] != 0xAA)
|
||||
{
|
||||
printf("MBR verification failed! Make sure your CID and consoleID are correct.");
|
||||
fclose(f_in);
|
||||
fclose(f_out);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// process NAND parts (encrypted and otherwise)
|
||||
rewind(f_in);
|
||||
|
||||
// process MBR
|
||||
dsi_set_ctr(&ctx, (u8*)base_ctr);
|
||||
file_copy_append(f_in, f_out, &ctx, 0, 0, 0x200);
|
||||
|
||||
|
||||
// process space before partition 1, including stage 2 bootloader etc
|
||||
file_copy_append(f_in, f_out, NULL, 0, 0x200, 0x10EE00);
|
||||
|
||||
// process twln
|
||||
printf("Processing twln...\n");
|
||||
dsi_set_ctr(&ctx, (u8*)base_ctr);
|
||||
dsi_add_ctr(&ctx, 0x10EE00 / 0x10);
|
||||
file_copy_append(f_in, f_out, &ctx, 1, 0x10EE00, 0x0CF00000);
|
||||
|
||||
// process space before partition 2
|
||||
file_copy_append(f_in, f_out, NULL, 0, 0x0CF00000, 0x0CF09A00);
|
||||
|
||||
// process twlp
|
||||
printf("Processing twlp...\n");
|
||||
dsi_set_ctr(&ctx, (u8*)base_ctr);
|
||||
dsi_add_ctr(&ctx, 0x0CF09A00 / 0x10);
|
||||
file_copy_append(f_in, f_out, &ctx, 1, 0x0CF09A00, 0x0EFC0000);
|
||||
|
||||
// process the rest, including unused (and unencrypted) third partition)
|
||||
file_copy_append(f_in, f_out, NULL, 0, 0x0EFC0000, 0x0F000000);
|
||||
|
||||
fclose(f_in);
|
||||
fclose(f_out);
|
||||
printf("Crypt complete!");
|
||||
}
|
||||
|
||||
/**
|
||||
* crypt system files (tickets, dev.kp) with ES Block crypto
|
||||
*/
|
||||
void es_crypt_file(char* in, char* out, u32 consoleID[2], bool encrypt, bool is3DS)
|
||||
{
|
||||
u8 es_system_keyY[16] = {0xE5, 0xCC, 0x5A, 0x8B, 0x56, 0xD0, 0xC9, 0x72, 0x9C, 0x17, 0xE8, 0xDC, 0x39, 0x12, 0x36, 0xA9};
|
||||
u32 in_size;
|
||||
u32 write_size = 0;
|
||||
int ret = 0;
|
||||
u32 normalkey[4];
|
||||
dsi_es_context ctx;
|
||||
|
||||
FILE* f_in = fopen(in,"r+b");
|
||||
FILE* f_out;
|
||||
if(!strcmp(in,out))
|
||||
f_out = fopen(out,"r+b");
|
||||
else
|
||||
f_out = fopen(out,"wb");
|
||||
if(f_in == NULL)
|
||||
{
|
||||
printf("Input filename invalid! %s", in);
|
||||
return;
|
||||
}
|
||||
if(f_out == NULL)
|
||||
{
|
||||
printf("Output filename invalid! %s", out);
|
||||
return;
|
||||
}
|
||||
fseek(f_in, 0, SEEK_END);
|
||||
in_size = ftell(f_in);
|
||||
rewind(f_in);
|
||||
|
||||
void* in_data = malloc(in_size);
|
||||
if(!in_data)
|
||||
{
|
||||
printf("Failed to allocate input file buf!");
|
||||
return;
|
||||
}
|
||||
fread(in_data, 1, in_size, f_in);
|
||||
|
||||
if(is3DS == false)
|
||||
{
|
||||
// Endian-swap the input ConsoleID (provided from tad footer)
|
||||
consoleID[1] = getbe32((u8*)consoleID);
|
||||
consoleID[0] = getbe32((u8*)consoleID+4);
|
||||
}
|
||||
// set up keys for crypto (consoleid is in reverse word order)
|
||||
tadsrl_keyX[2] = consoleID[1] ^ 0xC80C4B72;
|
||||
tadsrl_keyX[3] = consoleID[0];
|
||||
F_XY(normalkey, tadsrl_keyX, (u32*)es_system_keyY);
|
||||
dsi_es_init(&ctx, (u8*)normalkey);
|
||||
|
||||
if(encrypt == false)
|
||||
{
|
||||
// decrypt!
|
||||
write_size = in_size - 0x20;
|
||||
ret = dsi_es_decrypt(&ctx, in_data, in_data + write_size, write_size);
|
||||
if(ret == -1)
|
||||
{
|
||||
printf("ES magic check failed! Is your consoleID correct?");
|
||||
return;
|
||||
}
|
||||
else if(ret == -2)
|
||||
{
|
||||
printf("Decrypted file size is incorrect!");
|
||||
return;
|
||||
}
|
||||
else if(ret == -3)
|
||||
{
|
||||
printf("MAC mismatch! Continuing...");
|
||||
return;
|
||||
}
|
||||
fwrite(in_data, 1, write_size, f_out);
|
||||
printf("ES decrypt success!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// encrypt!
|
||||
u8 metablock[32];
|
||||
|
||||
dsi_es_encrypt(&ctx, in_data, metablock, in_size);
|
||||
fwrite(in_data, 1, in_size, f_out);
|
||||
fwrite(metablock, 1, 0x20, f_out);
|
||||
printf("ES encrypt complete!");
|
||||
}
|
||||
|
||||
fclose(f_in);
|
||||
fclose(f_out);
|
||||
free(in_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a string and get a byte array or contents of a file from it
|
||||
* returns 0 on success
|
||||
*/
|
||||
int read_hex_file_string(char* str, u8* buf, int len)
|
||||
{
|
||||
FILE* f = fopen(str, "rb");
|
||||
if(f)
|
||||
{
|
||||
fseek(f, 0L, SEEK_END);
|
||||
u32 fsize = ftell(f);
|
||||
rewind(f);
|
||||
if(fsize == len)
|
||||
{
|
||||
fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid file size for %s! Expected 0x%x, got 0x%x\n", str, len, fsize);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(hex2bytes(str, strlen(str), buf, len))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void display_help()
|
||||
{
|
||||
printf("Usage: twltool <command> [args]\n");
|
||||
printf("Commands:\n");
|
||||
printf(" nandcrypt\n");
|
||||
printf(" modcrypt\n");
|
||||
printf(" boot2\n");
|
||||
printf(" syscrypt\n");
|
||||
printf("nandcrypt: (de)crypt DSi NAND\n");
|
||||
printf(" --cid [file/hex CID] eMMC CID\n");
|
||||
printf(" --consoleid [file/hex ID] DSi ConsoleID\n");
|
||||
printf(" --in [infile] Input image\n");
|
||||
printf(" --out [outfile] Output file (optional)\n");
|
||||
printf(" --3ds Crypt 3DS TWLNAND\n");
|
||||
printf(" --3dsbrute Bruteforce 3DS ConsoleID\n");
|
||||
printf(" --cidfile [outfile] Output name for bruteforced CID (optional)\n");
|
||||
printf(" --n3ds New3DS bruteforce (use with --3ds)\n");
|
||||
printf("modcrypt: (de)crypt SRL modcrypt sections\n");
|
||||
printf(" --in [infile] Input SRL\n");
|
||||
printf(" --out [outfile] Output file (optional)\n");
|
||||
printf("boot2: decrypt boot2 image to arm7.bin and arm9.bin\n");
|
||||
printf(" --in [infile] Input image\n");
|
||||
printf(" --debug Crypt debug boot2 (devkits, TWL_FIRM, ...)\n");
|
||||
printf("syscrypt: crypt system files with ES block crypto (dev.kp, tickets, ...)\n");
|
||||
printf(" --in [infile] Input SRL\n");
|
||||
printf(" --out [outfile] Output file (optional)\n");
|
||||
printf(" --consoleid [file/hex ID] DSi ConsoleID\n");
|
||||
printf(" --encrypt Encrypt file\n");
|
||||
printf(" --3ds Using 3DS ConsoleID");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
u8 consoleID[8] = {0};
|
||||
u8 cid[16] = {0};
|
||||
char in[400] = {0};
|
||||
char out[400] = {0};
|
||||
char cidfile[400] = {0};
|
||||
bool is3DS = false;
|
||||
bool brute_cid = false;
|
||||
bool isN3DS = false;
|
||||
bool encrypt = false;
|
||||
|
||||
printf("TWLTool v1.6\n");
|
||||
printf(" by WulfyStylez\n");
|
||||
printf(" Special thanks to CaitSith2\n\n");
|
||||
if(argc <= 1)
|
||||
display_help();
|
||||
else
|
||||
{
|
||||
if(!strcmp(argv[1], "nandcrypt"))
|
||||
{
|
||||
if(argc < 6) {
|
||||
printf("Invalid options!\n");
|
||||
display_help();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
for(i = 0; i < argc; i++)
|
||||
{
|
||||
if(!strcmp(argv[i],"--consoleid")) {
|
||||
if(read_hex_file_string(argv[i+1], consoleID, 8))
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(!strcmp(argv[i],"--cid")) {
|
||||
if(read_hex_file_string(argv[i+1], cid, 16))
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(!strcmp(argv[i],"--3ds"))
|
||||
is3DS = true;
|
||||
if(!strcmp(argv[i],"--3dsbrute"))
|
||||
brute_cid = true;
|
||||
if(!strcmp(argv[i],"--n3ds"))
|
||||
isN3DS = true;
|
||||
if(!strcmp(argv[i],"--in")) {
|
||||
strcpy(in, argv[i+1]);
|
||||
}
|
||||
if(!strcmp(argv[i],"--out")) {
|
||||
strcpy(out, argv[i+1]);
|
||||
}
|
||||
if(!strcmp(argv[i],"--cidfile")) {
|
||||
strcpy(cidfile, argv[i+1]);
|
||||
}
|
||||
}
|
||||
if(in[0] == 0) {
|
||||
printf("Invalid filename!\n");
|
||||
display_help();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(out[0] == 0)
|
||||
strcpy(out,in);
|
||||
if(is3DS)
|
||||
nand_decrypt_3ds(cid, (u32*)consoleID, in, out, brute_cid, cidfile, isN3DS);
|
||||
else
|
||||
nand_decrypt_dsi(cid, (u32*)consoleID, in, out);
|
||||
}
|
||||
else if(!strcmp(argv[1], "modcrypt"))
|
||||
{
|
||||
if(argc < 4) {
|
||||
printf("Invalid options!\n");
|
||||
display_help();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
for(i = 0; i < argc; i++)
|
||||
{
|
||||
if(!strcmp(argv[i],"--in")) {
|
||||
strcpy(in, argv[i+1]);
|
||||
}
|
||||
if(!strcmp(argv[i],"--out")) {
|
||||
strcpy(out, argv[i+1]);
|
||||
}
|
||||
}
|
||||
if(in[0] == 0) {
|
||||
printf("Invalid filename!\n");
|
||||
display_help();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(out[0] == 0)
|
||||
strcpy(out,in);
|
||||
decrypt_srl(in, out);
|
||||
}
|
||||
else if(!strcmp(argv[1], "boot2"))
|
||||
{
|
||||
if(argc < 4) {
|
||||
printf("Invalid options!\n");
|
||||
display_help();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
for(i = 0; i < argc; i++)
|
||||
{
|
||||
if(!strcmp(argv[i],"--in")) {
|
||||
strcpy(in, argv[i+1]);
|
||||
}
|
||||
if(!strcmp(argv[i],"--debug")) {
|
||||
is3DS = 1;
|
||||
}
|
||||
}
|
||||
if(in[0] == 0) {
|
||||
printf("Invalid filename!\n");
|
||||
display_help();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
decrypt_boot2(in, is3DS);
|
||||
}
|
||||
else if(!strcmp(argv[1], "syscrypt"))
|
||||
{
|
||||
if(argc < 6) {
|
||||
printf("Invalid options!\n");
|
||||
display_help();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
for(i = 0; i < argc; i++)
|
||||
{
|
||||
if(!strcmp(argv[i],"--in")) {
|
||||
strcpy(in, argv[i+1]);
|
||||
}
|
||||
if(!strcmp(argv[i],"--out")) {
|
||||
strcpy(out, argv[i+1]);
|
||||
}
|
||||
if(!strcmp(argv[i],"--consoleid")) {
|
||||
if(read_hex_file_string(argv[i+1], consoleID, 8))
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(!strcmp(argv[i],"--encrypt")) {
|
||||
encrypt = true;
|
||||
}
|
||||
if(!strcmp(argv[i],"--3ds"))
|
||||
is3DS = true;
|
||||
}
|
||||
if(in[0] == 0) {
|
||||
printf("Invalid input filename! %s\n", in);
|
||||
display_help();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(out[0] == 0)
|
||||
strcpy(out,in);
|
||||
es_crypt_file(in, out, (u32*)consoleID, encrypt, is3DS);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid command!\n");
|
||||
display_help();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
1164
polarssl/aes.c
Normal file
1164
polarssl/aes.c
Normal file
File diff suppressed because it is too large
Load Diff
139
polarssl/aes.h
Normal file
139
polarssl/aes.h
Normal file
@ -0,0 +1,139 @@
|
||||
/**
|
||||
* \file aes.h
|
||||
*
|
||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef POLARSSL_AES_H
|
||||
#define POLARSSL_AES_H
|
||||
|
||||
#define AES_ENCRYPT 1
|
||||
#define AES_DECRYPT 0
|
||||
|
||||
#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0800
|
||||
#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0810
|
||||
|
||||
/**
|
||||
* \brief AES context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int nr; /*!< number of rounds */
|
||||
unsigned long *rk; /*!< AES round keys */
|
||||
unsigned long buf[68]; /*!< unaligned data */
|
||||
}
|
||||
aes_context;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (encryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key encryption key
|
||||
* \param keysize must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int aes_setkey_enc( aes_context *ctx, const unsigned char *key, int keysize );
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (decryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key decryption key
|
||||
* \param keysize must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int aes_setkey_dec( aes_context *ctx, const unsigned char *key, int keysize );
|
||||
|
||||
/**
|
||||
* \brief AES-ECB block encryption/decryption
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param input 16-byte input block
|
||||
* \param output 16-byte output block
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_ecb( aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
/**
|
||||
* \brief AES-CBC buffer encryption/decryption
|
||||
* Length should be a multiple of the block
|
||||
* size (16 bytes)
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
|
||||
*/
|
||||
int aes_crypt_cbc( aes_context *ctx,
|
||||
int mode,
|
||||
int length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief AES-CFB128 buffer encryption/decryption.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv_off offset in IV (updated after use)
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_cfb128( aes_context *ctx,
|
||||
int mode,
|
||||
int length,
|
||||
int *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int aes_self_test( int verbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* aes.h */
|
2038
polarssl/bignum.c
Normal file
2038
polarssl/bignum.c
Normal file
File diff suppressed because it is too large
Load Diff
533
polarssl/bignum.h
Normal file
533
polarssl/bignum.h
Normal file
@ -0,0 +1,533 @@
|
||||
/**
|
||||
* \file bignum.h
|
||||
*
|
||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef POLARSSL_BIGNUM_H
|
||||
#define POLARSSL_BIGNUM_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define POLARSSL_ERR_MPI_FILE_IO_ERROR 0x0002
|
||||
#define POLARSSL_ERR_MPI_BAD_INPUT_DATA 0x0004
|
||||
#define POLARSSL_ERR_MPI_INVALID_CHARACTER 0x0006
|
||||
#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL 0x0008
|
||||
#define POLARSSL_ERR_MPI_NEGATIVE_VALUE 0x000A
|
||||
#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO 0x000C
|
||||
#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE 0x000E
|
||||
|
||||
#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
|
||||
|
||||
/*
|
||||
* Define the base integer type, architecture-wise
|
||||
*/
|
||||
#if defined(POLARSSL_HAVE_INT8)
|
||||
typedef unsigned char t_int;
|
||||
typedef unsigned short t_dbl;
|
||||
#else
|
||||
#if defined(POLARSSL_HAVE_INT16)
|
||||
typedef unsigned short t_int;
|
||||
typedef unsigned long t_dbl;
|
||||
#else
|
||||
typedef unsigned long t_int;
|
||||
#if defined(_MSC_VER) && defined(_M_IX86)
|
||||
typedef unsigned __int64 t_dbl;
|
||||
#else
|
||||
#if defined(__amd64__) || defined(__x86_64__) || \
|
||||
defined(__ppc64__) || defined(__powerpc64__) || \
|
||||
defined(__ia64__) || defined(__alpha__)
|
||||
typedef unsigned int t_dbl __attribute__((mode(TI)));
|
||||
#else
|
||||
#if defined(POLARSSL_HAVE_LONGLONG)
|
||||
typedef unsigned long long t_dbl;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief MPI structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int s; /*!< integer sign */
|
||||
int n; /*!< total # of limbs */
|
||||
t_int *p; /*!< pointer to limbs */
|
||||
}
|
||||
mpi;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Initialize one or more mpi
|
||||
*/
|
||||
void mpi_init( mpi *X, ... );
|
||||
|
||||
/**
|
||||
* \brief Unallocate one or more mpi
|
||||
*/
|
||||
void mpi_free( mpi *X, ... );
|
||||
|
||||
/**
|
||||
* \brief Enlarge to the specified number of limbs
|
||||
*
|
||||
* \param X MPI to grow
|
||||
* \param nblimbs The target number of limbs
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_grow( mpi *X, int nblimbs );
|
||||
|
||||
/**
|
||||
* \brief Copy the contents of Y into X
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param Y Source MPI
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_copy( mpi *X, const mpi *Y );
|
||||
|
||||
/**
|
||||
* \brief Swap the contents of X and Y
|
||||
*
|
||||
* \param X First MPI value
|
||||
* \param Y Second MPI value
|
||||
*/
|
||||
void mpi_swap( mpi *X, mpi *Y );
|
||||
|
||||
/**
|
||||
* \brief Set value from integer
|
||||
*
|
||||
* \param X MPI to set
|
||||
* \param z Value to use
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_lset( mpi *X, int z );
|
||||
|
||||
/**
|
||||
* \brief Return the number of least significant bits
|
||||
*
|
||||
* \param X MPI to use
|
||||
*/
|
||||
int mpi_lsb( const mpi *X );
|
||||
|
||||
/**
|
||||
* \brief Return the number of most significant bits
|
||||
*
|
||||
* \param X MPI to use
|
||||
*/
|
||||
int mpi_msb( const mpi *X );
|
||||
|
||||
/**
|
||||
* \brief Return the total size in bytes
|
||||
*
|
||||
* \param X MPI to use
|
||||
*/
|
||||
int mpi_size( const mpi *X );
|
||||
|
||||
/**
|
||||
* \brief Import from an ASCII string
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param radix Input numeric base
|
||||
* \param s Null-terminated string buffer
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
|
||||
*/
|
||||
int mpi_read_string( mpi *X, int radix, const char *s );
|
||||
|
||||
/**
|
||||
* \brief Export into an ASCII string
|
||||
*
|
||||
* \param X Source MPI
|
||||
* \param radix Output numeric base
|
||||
* \param s String buffer
|
||||
* \param slen String buffer size
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code.
|
||||
* *slen is always updated to reflect the amount
|
||||
* of data that has (or would have) been written.
|
||||
*
|
||||
* \note Call this function with *slen = 0 to obtain the
|
||||
* minimum required buffer size in *slen.
|
||||
*/
|
||||
int mpi_write_string( const mpi *X, int radix, char *s, int *slen );
|
||||
|
||||
/**
|
||||
* \brief Read X from an opened file
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param radix Input numeric base
|
||||
* \param fin Input file handle
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
|
||||
*/
|
||||
int mpi_read_file( mpi *X, int radix, FILE *fin );
|
||||
|
||||
/**
|
||||
* \brief Write X into an opened file, or stdout if fout is NULL
|
||||
*
|
||||
* \param p Prefix, can be NULL
|
||||
* \param X Source MPI
|
||||
* \param radix Output numeric base
|
||||
* \param fout Output file handle (can be NULL)
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
|
||||
*
|
||||
* \note Set fout == NULL to print X on the console.
|
||||
*/
|
||||
int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
|
||||
|
||||
/**
|
||||
* \brief Import X from unsigned binary data, big endian
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param buf Input buffer
|
||||
* \param buflen Input buffer size
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_read_binary( mpi *X, const unsigned char *buf, int buflen );
|
||||
|
||||
/**
|
||||
* \brief Export X into unsigned binary data, big endian
|
||||
*
|
||||
* \param X Source MPI
|
||||
* \param buf Output buffer
|
||||
* \param buflen Output buffer size
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
|
||||
*/
|
||||
int mpi_write_binary( const mpi *X, unsigned char *buf, int buflen );
|
||||
|
||||
/**
|
||||
* \brief Left-shift: X <<= count
|
||||
*
|
||||
* \param X MPI to shift
|
||||
* \param count Amount to shift
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_shift_l( mpi *X, int count );
|
||||
|
||||
/**
|
||||
* \brief Right-shift: X >>= count
|
||||
*
|
||||
* \param X MPI to shift
|
||||
* \param count Amount to shift
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_shift_r( mpi *X, int count );
|
||||
|
||||
/**
|
||||
* \brief Compare unsigned values
|
||||
*
|
||||
* \param X Left-hand MPI
|
||||
* \param Y Right-hand MPI
|
||||
*
|
||||
* \return 1 if |X| is greater than |Y|,
|
||||
* -1 if |X| is lesser than |Y| or
|
||||
* 0 if |X| is equal to |Y|
|
||||
*/
|
||||
int mpi_cmp_abs( const mpi *X, const mpi *Y );
|
||||
|
||||
/**
|
||||
* \brief Compare signed values
|
||||
*
|
||||
* \param X Left-hand MPI
|
||||
* \param Y Right-hand MPI
|
||||
*
|
||||
* \return 1 if X is greater than Y,
|
||||
* -1 if X is lesser than Y or
|
||||
* 0 if X is equal to Y
|
||||
*/
|
||||
int mpi_cmp_mpi( const mpi *X, const mpi *Y );
|
||||
|
||||
/**
|
||||
* \brief Compare signed values
|
||||
*
|
||||
* \param X Left-hand MPI
|
||||
* \param z The integer value to compare to
|
||||
*
|
||||
* \return 1 if X is greater than z,
|
||||
* -1 if X is lesser than z or
|
||||
* 0 if X is equal to z
|
||||
*/
|
||||
int mpi_cmp_int( const mpi *X, int z );
|
||||
|
||||
/**
|
||||
* \brief Unsigned addition: X = |A| + |B|
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param B Right-hand MPI
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_add_abs( mpi *X, const mpi *A, const mpi *B );
|
||||
|
||||
/**
|
||||
* \brief Unsigned substraction: X = |A| - |B|
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param B Right-hand MPI
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
|
||||
*/
|
||||
int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B );
|
||||
|
||||
/**
|
||||
* \brief Signed addition: X = A + B
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param B Right-hand MPI
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B );
|
||||
|
||||
/**
|
||||
* \brief Signed substraction: X = A - B
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param B Right-hand MPI
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B );
|
||||
|
||||
/**
|
||||
* \brief Signed addition: X = A + b
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param b The integer value to add
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_add_int( mpi *X, const mpi *A, int b );
|
||||
|
||||
/**
|
||||
* \brief Signed substraction: X = A - b
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param b The integer value to subtract
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_sub_int( mpi *X, const mpi *A, int b );
|
||||
|
||||
/**
|
||||
* \brief Baseline multiplication: X = A * B
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param B Right-hand MPI
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
|
||||
|
||||
/**
|
||||
* \brief Baseline multiplication: X = A * b
|
||||
* Note: b is an unsigned integer type, thus
|
||||
* Negative values of b are ignored.
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param b The integer value to multiply with
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_mul_int( mpi *X, const mpi *A, t_int b );
|
||||
|
||||
/**
|
||||
* \brief Division by mpi: A = Q * B + R
|
||||
*
|
||||
* \param Q Destination MPI for the quotient
|
||||
* \param R Destination MPI for the rest value
|
||||
* \param A Left-hand MPI
|
||||
* \param B Right-hand MPI
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed,
|
||||
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
|
||||
*
|
||||
* \note Either Q or R can be NULL.
|
||||
*/
|
||||
int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B );
|
||||
|
||||
/**
|
||||
* \brief Division by int: A = Q * b + R
|
||||
*
|
||||
* \param Q Destination MPI for the quotient
|
||||
* \param R Destination MPI for the rest value
|
||||
* \param A Left-hand MPI
|
||||
* \param b Integer to divide by
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed,
|
||||
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
|
||||
*
|
||||
* \note Either Q or R can be NULL.
|
||||
*/
|
||||
int mpi_div_int( mpi *Q, mpi *R, const mpi *A, int b );
|
||||
|
||||
/**
|
||||
* \brief Modulo: R = A mod B
|
||||
*
|
||||
* \param R Destination MPI for the rest value
|
||||
* \param A Left-hand MPI
|
||||
* \param B Right-hand MPI
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed,
|
||||
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0,
|
||||
* POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0
|
||||
*/
|
||||
int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B );
|
||||
|
||||
/**
|
||||
* \brief Modulo: r = A mod b
|
||||
*
|
||||
* \param r Destination t_int
|
||||
* \param A Left-hand MPI
|
||||
* \param b Integer to divide by
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed,
|
||||
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0,
|
||||
* POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0
|
||||
*/
|
||||
int mpi_mod_int( t_int *r, const mpi *A, int b );
|
||||
|
||||
/**
|
||||
* \brief Sliding-window exponentiation: X = A^E mod N
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param E Exponent MPI
|
||||
* \param N Modular MPI
|
||||
* \param _RR Speed-up MPI used for recalculations
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed,
|
||||
* POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even
|
||||
*
|
||||
* \note _RR is used to avoid re-computing R*R mod N across
|
||||
* multiple calls, which speeds up things a bit. It can
|
||||
* be set to NULL if the extra performance is unneeded.
|
||||
*/
|
||||
int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR );
|
||||
|
||||
/**
|
||||
* \brief Greatest common divisor: G = gcd(A, B)
|
||||
*
|
||||
* \param G Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param B Right-hand MPI
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed
|
||||
*/
|
||||
int mpi_gcd( mpi *G, const mpi *A, const mpi *B );
|
||||
|
||||
/**
|
||||
* \brief Modular inverse: X = A^-1 mod N
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param A Left-hand MPI
|
||||
* \param N Right-hand MPI
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* 1 if memory allocation failed,
|
||||
* POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
|
||||
POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
|
||||
*/
|
||||
int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N );
|
||||
|
||||
/**
|
||||
* \brief Miller-Rabin primality test
|
||||
*
|
||||
* \param X MPI to check
|
||||
* \param f_rng RNG function
|
||||
* \param p_rng RNG parameter
|
||||
*
|
||||
* \return 0 if successful (probably prime),
|
||||
* 1 if memory allocation failed,
|
||||
* POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
|
||||
*/
|
||||
int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng );
|
||||
|
||||
/**
|
||||
* \brief Prime number generation
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param nbits Required size of X in bits
|
||||
* \param dh_flag If 1, then (X-1)/2 will be prime too
|
||||
* \param f_rng RNG function
|
||||
* \param p_rng RNG parameter
|
||||
*
|
||||
* \return 0 if successful (probably prime),
|
||||
* 1 if memory allocation failed,
|
||||
* POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
|
||||
*/
|
||||
int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
|
||||
int (*f_rng)(void *), void *p_rng );
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int mpi_self_test( int verbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* bignum.h */
|
736
polarssl/bn_mul.h
Normal file
736
polarssl/bn_mul.h
Normal file
@ -0,0 +1,736 @@
|
||||
/**
|
||||
* \file bn_mul.h
|
||||
*
|
||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/*
|
||||
* Multiply source vector [s] with b, add result
|
||||
* to destination vector [d] and set carry c.
|
||||
*
|
||||
* Currently supports:
|
||||
*
|
||||
* . IA-32 (386+) . AMD64 / EM64T
|
||||
* . IA-32 (SSE2) . Motorola 68000
|
||||
* . PowerPC, 32-bit . MicroBlaze
|
||||
* . PowerPC, 64-bit . TriCore
|
||||
* . SPARC v8 . ARM v3+
|
||||
* . Alpha . MIPS32
|
||||
* . C, longlong . C, generic
|
||||
*/
|
||||
#ifndef POLARSSL_BN_MUL_H
|
||||
#define POLARSSL_BN_MUL_H
|
||||
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#if defined(POLARSSL_HAVE_ASM)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__i386__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( " \
|
||||
movl %%ebx, %0; \
|
||||
movl %5, %%esi; \
|
||||
movl %6, %%edi; \
|
||||
movl %7, %%ecx; \
|
||||
movl %8, %%ebx; \
|
||||
"
|
||||
|
||||
#define MULADDC_CORE \
|
||||
" \
|
||||
lodsl; \
|
||||
mull %%ebx; \
|
||||
addl %%ecx, %%eax; \
|
||||
adcl $0, %%edx; \
|
||||
addl (%%edi), %%eax; \
|
||||
adcl $0, %%edx; \
|
||||
movl %%edx, %%ecx; \
|
||||
stosl; \
|
||||
"
|
||||
|
||||
#if defined(POLARSSL_HAVE_SSE2)
|
||||
|
||||
#define MULADDC_HUIT \
|
||||
" \
|
||||
movd %%ecx, %%mm1; \
|
||||
movd %%ebx, %%mm0; \
|
||||
movd (%%edi), %%mm3; \
|
||||
paddq %%mm3, %%mm1; \
|
||||
movd (%%esi), %%mm2; \
|
||||
pmuludq %%mm0, %%mm2; \
|
||||
movd 4(%%esi), %%mm4; \
|
||||
pmuludq %%mm0, %%mm4; \
|
||||
movd 8(%%esi), %%mm6; \
|
||||
pmuludq %%mm0, %%mm6; \
|
||||
movd 12(%%esi), %%mm7; \
|
||||
pmuludq %%mm0, %%mm7; \
|
||||
paddq %%mm2, %%mm1; \
|
||||
movd 4(%%edi), %%mm3; \
|
||||
paddq %%mm4, %%mm3; \
|
||||
movd 8(%%edi), %%mm5; \
|
||||
paddq %%mm6, %%mm5; \
|
||||
movd 12(%%edi), %%mm4; \
|
||||
paddq %%mm4, %%mm7; \
|
||||
movd %%mm1, (%%edi); \
|
||||
movd 16(%%esi), %%mm2; \
|
||||
pmuludq %%mm0, %%mm2; \
|
||||
psrlq $32, %%mm1; \
|
||||
movd 20(%%esi), %%mm4; \
|
||||
pmuludq %%mm0, %%mm4; \
|
||||
paddq %%mm3, %%mm1; \
|
||||
movd 24(%%esi), %%mm6; \
|
||||
pmuludq %%mm0, %%mm6; \
|
||||
movd %%mm1, 4(%%edi); \
|
||||
psrlq $32, %%mm1; \
|
||||
movd 28(%%esi), %%mm3; \
|
||||
pmuludq %%mm0, %%mm3; \
|
||||
paddq %%mm5, %%mm1; \
|
||||
movd 16(%%edi), %%mm5; \
|
||||
paddq %%mm5, %%mm2; \
|
||||
movd %%mm1, 8(%%edi); \
|
||||
psrlq $32, %%mm1; \
|
||||
paddq %%mm7, %%mm1; \
|
||||
movd 20(%%edi), %%mm5; \
|
||||
paddq %%mm5, %%mm4; \
|
||||
movd %%mm1, 12(%%edi); \
|
||||
psrlq $32, %%mm1; \
|
||||
paddq %%mm2, %%mm1; \
|
||||
movd 24(%%edi), %%mm5; \
|
||||
paddq %%mm5, %%mm6; \
|
||||
movd %%mm1, 16(%%edi); \
|
||||
psrlq $32, %%mm1; \
|
||||
paddq %%mm4, %%mm1; \
|
||||
movd 28(%%edi), %%mm5; \
|
||||
paddq %%mm5, %%mm3; \
|
||||
movd %%mm1, 20(%%edi); \
|
||||
psrlq $32, %%mm1; \
|
||||
paddq %%mm6, %%mm1; \
|
||||
movd %%mm1, 24(%%edi); \
|
||||
psrlq $32, %%mm1; \
|
||||
paddq %%mm3, %%mm1; \
|
||||
movd %%mm1, 28(%%edi); \
|
||||
addl $32, %%edi; \
|
||||
addl $32, %%esi; \
|
||||
psrlq $32, %%mm1; \
|
||||
movd %%mm1, %%ecx; \
|
||||
"
|
||||
|
||||
#define MULADDC_STOP \
|
||||
" \
|
||||
emms; \
|
||||
movl %4, %%ebx; \
|
||||
movl %%ecx, %1; \
|
||||
movl %%edi, %2; \
|
||||
movl %%esi, %3; \
|
||||
" \
|
||||
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
|
||||
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
|
||||
: "eax", "ecx", "edx", "esi", "edi" \
|
||||
);
|
||||
|
||||
#else
|
||||
|
||||
#define MULADDC_STOP \
|
||||
" \
|
||||
movl %4, %%ebx; \
|
||||
movl %%ecx, %1; \
|
||||
movl %%edi, %2; \
|
||||
movl %%esi, %3; \
|
||||
" \
|
||||
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
|
||||
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
|
||||
: "eax", "ecx", "edx", "esi", "edi" \
|
||||
);
|
||||
#endif /* SSE2 */
|
||||
#endif /* i386 */
|
||||
|
||||
#if defined(__amd64__) || defined (__x86_64__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "movq %0, %%rsi " :: "m" (s)); \
|
||||
asm( "movq %0, %%rdi " :: "m" (d)); \
|
||||
asm( "movq %0, %%rcx " :: "m" (c)); \
|
||||
asm( "movq %0, %%rbx " :: "m" (b)); \
|
||||
asm( "xorq %r8, %r8 " );
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "movq (%rsi),%rax " ); \
|
||||
asm( "mulq %rbx " ); \
|
||||
asm( "addq $8, %rsi " ); \
|
||||
asm( "addq %rcx, %rax " ); \
|
||||
asm( "movq %r8, %rcx " ); \
|
||||
asm( "adcq $0, %rdx " ); \
|
||||
asm( "nop " ); \
|
||||
asm( "addq %rax, (%rdi) " ); \
|
||||
asm( "adcq %rdx, %rcx " ); \
|
||||
asm( "addq $8, %rdi " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "movq %%rcx, %0 " : "=m" (c)); \
|
||||
asm( "movq %%rdi, %0 " : "=m" (d)); \
|
||||
asm( "movq %%rsi, %0 " : "=m" (s) :: \
|
||||
"rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
|
||||
|
||||
#endif /* AMD64 */
|
||||
|
||||
#if defined(__mc68020__) || defined(__mcpu32__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "movl %0, %%a2 " :: "m" (s)); \
|
||||
asm( "movl %0, %%a3 " :: "m" (d)); \
|
||||
asm( "movl %0, %%d3 " :: "m" (c)); \
|
||||
asm( "movl %0, %%d2 " :: "m" (b)); \
|
||||
asm( "moveq #0, %d0 " );
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "movel %a2@+, %d1 " ); \
|
||||
asm( "mulul %d2, %d4:%d1 " ); \
|
||||
asm( "addl %d3, %d1 " ); \
|
||||
asm( "addxl %d0, %d4 " ); \
|
||||
asm( "moveq #0, %d3 " ); \
|
||||
asm( "addl %d1, %a3@+ " ); \
|
||||
asm( "addxl %d4, %d3 " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "movl %%d3, %0 " : "=m" (c)); \
|
||||
asm( "movl %%a3, %0 " : "=m" (d)); \
|
||||
asm( "movl %%a2, %0 " : "=m" (s) :: \
|
||||
"d0", "d1", "d2", "d3", "d4", "a2", "a3" );
|
||||
|
||||
#define MULADDC_HUIT \
|
||||
asm( "movel %a2@+, %d1 " ); \
|
||||
asm( "mulul %d2, %d4:%d1 " ); \
|
||||
asm( "addxl %d3, %d1 " ); \
|
||||
asm( "addxl %d0, %d4 " ); \
|
||||
asm( "addl %d1, %a3@+ " ); \
|
||||
asm( "movel %a2@+, %d1 " ); \
|
||||
asm( "mulul %d2, %d3:%d1 " ); \
|
||||
asm( "addxl %d4, %d1 " ); \
|
||||
asm( "addxl %d0, %d3 " ); \
|
||||
asm( "addl %d1, %a3@+ " ); \
|
||||
asm( "movel %a2@+, %d1 " ); \
|
||||
asm( "mulul %d2, %d4:%d1 " ); \
|
||||
asm( "addxl %d3, %d1 " ); \
|
||||
asm( "addxl %d0, %d4 " ); \
|
||||
asm( "addl %d1, %a3@+ " ); \
|
||||
asm( "movel %a2@+, %d1 " ); \
|
||||
asm( "mulul %d2, %d3:%d1 " ); \
|
||||
asm( "addxl %d4, %d1 " ); \
|
||||
asm( "addxl %d0, %d3 " ); \
|
||||
asm( "addl %d1, %a3@+ " ); \
|
||||
asm( "movel %a2@+, %d1 " ); \
|
||||
asm( "mulul %d2, %d4:%d1 " ); \
|
||||
asm( "addxl %d3, %d1 " ); \
|
||||
asm( "addxl %d0, %d4 " ); \
|
||||
asm( "addl %d1, %a3@+ " ); \
|
||||
asm( "movel %a2@+, %d1 " ); \
|
||||
asm( "mulul %d2, %d3:%d1 " ); \
|
||||
asm( "addxl %d4, %d1 " ); \
|
||||
asm( "addxl %d0, %d3 " ); \
|
||||
asm( "addl %d1, %a3@+ " ); \
|
||||
asm( "movel %a2@+, %d1 " ); \
|
||||
asm( "mulul %d2, %d4:%d1 " ); \
|
||||
asm( "addxl %d3, %d1 " ); \
|
||||
asm( "addxl %d0, %d4 " ); \
|
||||
asm( "addl %d1, %a3@+ " ); \
|
||||
asm( "movel %a2@+, %d1 " ); \
|
||||
asm( "mulul %d2, %d3:%d1 " ); \
|
||||
asm( "addxl %d4, %d1 " ); \
|
||||
asm( "addxl %d0, %d3 " ); \
|
||||
asm( "addl %d1, %a3@+ " ); \
|
||||
asm( "addxl %d0, %d3 " );
|
||||
|
||||
#endif /* MC68000 */
|
||||
|
||||
#if defined(__powerpc__) || defined(__ppc__)
|
||||
#if defined(__powerpc64__) || defined(__ppc64__)
|
||||
|
||||
#if defined(__MACH__) && defined(__APPLE__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "ld r3, %0 " :: "m" (s)); \
|
||||
asm( "ld r4, %0 " :: "m" (d)); \
|
||||
asm( "ld r5, %0 " :: "m" (c)); \
|
||||
asm( "ld r6, %0 " :: "m" (b)); \
|
||||
asm( "addi r3, r3, -8 " ); \
|
||||
asm( "addi r4, r4, -8 " ); \
|
||||
asm( "addic r5, r5, 0 " );
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "ldu r7, 8(r3) " ); \
|
||||
asm( "mulld r8, r7, r6 " ); \
|
||||
asm( "mulhdu r9, r7, r6 " ); \
|
||||
asm( "adde r8, r8, r5 " ); \
|
||||
asm( "ld r7, 8(r4) " ); \
|
||||
asm( "addze r5, r9 " ); \
|
||||
asm( "addc r8, r8, r7 " ); \
|
||||
asm( "stdu r8, 8(r4) " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "addze r5, r5 " ); \
|
||||
asm( "addi r4, r4, 8 " ); \
|
||||
asm( "addi r3, r3, 8 " ); \
|
||||
asm( "std r5, %0 " : "=m" (c)); \
|
||||
asm( "std r4, %0 " : "=m" (d)); \
|
||||
asm( "std r3, %0 " : "=m" (s) :: \
|
||||
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
|
||||
|
||||
#else
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "ld %%r3, %0 " :: "m" (s)); \
|
||||
asm( "ld %%r4, %0 " :: "m" (d)); \
|
||||
asm( "ld %%r5, %0 " :: "m" (c)); \
|
||||
asm( "ld %%r6, %0 " :: "m" (b)); \
|
||||
asm( "addi %r3, %r3, -8 " ); \
|
||||
asm( "addi %r4, %r4, -8 " ); \
|
||||
asm( "addic %r5, %r5, 0 " );
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "ldu %r7, 8(%r3) " ); \
|
||||
asm( "mulld %r8, %r7, %r6 " ); \
|
||||
asm( "mulhdu %r9, %r7, %r6 " ); \
|
||||
asm( "adde %r8, %r8, %r5 " ); \
|
||||
asm( "ld %r7, 8(%r4) " ); \
|
||||
asm( "addze %r5, %r9 " ); \
|
||||
asm( "addc %r8, %r8, %r7 " ); \
|
||||
asm( "stdu %r8, 8(%r4) " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "addze %r5, %r5 " ); \
|
||||
asm( "addi %r4, %r4, 8 " ); \
|
||||
asm( "addi %r3, %r3, 8 " ); \
|
||||
asm( "std %%r5, %0 " : "=m" (c)); \
|
||||
asm( "std %%r4, %0 " : "=m" (d)); \
|
||||
asm( "std %%r3, %0 " : "=m" (s) :: \
|
||||
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
|
||||
|
||||
#endif
|
||||
|
||||
#else /* PPC32 */
|
||||
|
||||
#if defined(__MACH__) && defined(__APPLE__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "lwz r3, %0 " :: "m" (s)); \
|
||||
asm( "lwz r4, %0 " :: "m" (d)); \
|
||||
asm( "lwz r5, %0 " :: "m" (c)); \
|
||||
asm( "lwz r6, %0 " :: "m" (b)); \
|
||||
asm( "addi r3, r3, -4 " ); \
|
||||
asm( "addi r4, r4, -4 " ); \
|
||||
asm( "addic r5, r5, 0 " );
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "lwzu r7, 4(r3) " ); \
|
||||
asm( "mullw r8, r7, r6 " ); \
|
||||
asm( "mulhwu r9, r7, r6 " ); \
|
||||
asm( "adde r8, r8, r5 " ); \
|
||||
asm( "lwz r7, 4(r4) " ); \
|
||||
asm( "addze r5, r9 " ); \
|
||||
asm( "addc r8, r8, r7 " ); \
|
||||
asm( "stwu r8, 4(r4) " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "addze r5, r5 " ); \
|
||||
asm( "addi r4, r4, 4 " ); \
|
||||
asm( "addi r3, r3, 4 " ); \
|
||||
asm( "stw r5, %0 " : "=m" (c)); \
|
||||
asm( "stw r4, %0 " : "=m" (d)); \
|
||||
asm( "stw r3, %0 " : "=m" (s) :: \
|
||||
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
|
||||
|
||||
#else
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "lwz %%r3, %0 " :: "m" (s)); \
|
||||
asm( "lwz %%r4, %0 " :: "m" (d)); \
|
||||
asm( "lwz %%r5, %0 " :: "m" (c)); \
|
||||
asm( "lwz %%r6, %0 " :: "m" (b)); \
|
||||
asm( "addi %r3, %r3, -4 " ); \
|
||||
asm( "addi %r4, %r4, -4 " ); \
|
||||
asm( "addic %r5, %r5, 0 " );
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "lwzu %r7, 4(%r3) " ); \
|
||||
asm( "mullw %r8, %r7, %r6 " ); \
|
||||
asm( "mulhwu %r9, %r7, %r6 " ); \
|
||||
asm( "adde %r8, %r8, %r5 " ); \
|
||||
asm( "lwz %r7, 4(%r4) " ); \
|
||||
asm( "addze %r5, %r9 " ); \
|
||||
asm( "addc %r8, %r8, %r7 " ); \
|
||||
asm( "stwu %r8, 4(%r4) " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "addze %r5, %r5 " ); \
|
||||
asm( "addi %r4, %r4, 4 " ); \
|
||||
asm( "addi %r3, %r3, 4 " ); \
|
||||
asm( "stw %%r5, %0 " : "=m" (c)); \
|
||||
asm( "stw %%r4, %0 " : "=m" (d)); \
|
||||
asm( "stw %%r3, %0 " : "=m" (s) :: \
|
||||
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PPC32 */
|
||||
#endif /* PPC64 */
|
||||
|
||||
#if defined(__sparc__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "ld %0, %%o0 " :: "m" (s)); \
|
||||
asm( "ld %0, %%o1 " :: "m" (d)); \
|
||||
asm( "ld %0, %%o2 " :: "m" (c)); \
|
||||
asm( "ld %0, %%o3 " :: "m" (b));
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "ld [%o0], %o4 " ); \
|
||||
asm( "inc 4, %o0 " ); \
|
||||
asm( "ld [%o1], %o5 " ); \
|
||||
asm( "umul %o3, %o4, %o4 " ); \
|
||||
asm( "addcc %o4, %o2, %o4 " ); \
|
||||
asm( "rd %y, %g1 " ); \
|
||||
asm( "addx %g1, 0, %g1 " ); \
|
||||
asm( "addcc %o4, %o5, %o4 " ); \
|
||||
asm( "st %o4, [%o1] " ); \
|
||||
asm( "addx %g1, 0, %o2 " ); \
|
||||
asm( "inc 4, %o1 " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "st %%o2, %0 " : "=m" (c)); \
|
||||
asm( "st %%o1, %0 " : "=m" (d)); \
|
||||
asm( "st %%o0, %0 " : "=m" (s) :: \
|
||||
"g1", "o0", "o1", "o2", "o3", "o4", "o5" );
|
||||
|
||||
#endif /* SPARCv8 */
|
||||
|
||||
#if defined(__microblaze__) || defined(microblaze)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "lwi r3, %0 " :: "m" (s)); \
|
||||
asm( "lwi r4, %0 " :: "m" (d)); \
|
||||
asm( "lwi r5, %0 " :: "m" (c)); \
|
||||
asm( "lwi r6, %0 " :: "m" (b)); \
|
||||
asm( "andi r7, r6, 0xffff" ); \
|
||||
asm( "bsrli r6, r6, 16 " );
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "lhui r8, r3, 0 " ); \
|
||||
asm( "addi r3, r3, 2 " ); \
|
||||
asm( "lhui r9, r3, 0 " ); \
|
||||
asm( "addi r3, r3, 2 " ); \
|
||||
asm( "mul r10, r9, r6 " ); \
|
||||
asm( "mul r11, r8, r7 " ); \
|
||||
asm( "mul r12, r9, r7 " ); \
|
||||
asm( "mul r13, r8, r6 " ); \
|
||||
asm( "bsrli r8, r10, 16 " ); \
|
||||
asm( "bsrli r9, r11, 16 " ); \
|
||||
asm( "add r13, r13, r8 " ); \
|
||||
asm( "add r13, r13, r9 " ); \
|
||||
asm( "bslli r10, r10, 16 " ); \
|
||||
asm( "bslli r11, r11, 16 " ); \
|
||||
asm( "add r12, r12, r10 " ); \
|
||||
asm( "addc r13, r13, r0 " ); \
|
||||
asm( "add r12, r12, r11 " ); \
|
||||
asm( "addc r13, r13, r0 " ); \
|
||||
asm( "lwi r10, r4, 0 " ); \
|
||||
asm( "add r12, r12, r10 " ); \
|
||||
asm( "addc r13, r13, r0 " ); \
|
||||
asm( "add r12, r12, r5 " ); \
|
||||
asm( "addc r5, r13, r0 " ); \
|
||||
asm( "swi r12, r4, 0 " ); \
|
||||
asm( "addi r4, r4, 4 " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "swi r5, %0 " : "=m" (c)); \
|
||||
asm( "swi r4, %0 " : "=m" (d)); \
|
||||
asm( "swi r3, %0 " : "=m" (s) :: \
|
||||
"r3", "r4" , "r5" , "r6" , "r7" , "r8" , \
|
||||
"r9", "r10", "r11", "r12", "r13" );
|
||||
|
||||
#endif /* MicroBlaze */
|
||||
|
||||
#if defined(__tricore__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "ld.a %%a2, %0 " :: "m" (s)); \
|
||||
asm( "ld.a %%a3, %0 " :: "m" (d)); \
|
||||
asm( "ld.w %%d4, %0 " :: "m" (c)); \
|
||||
asm( "ld.w %%d1, %0 " :: "m" (b)); \
|
||||
asm( "xor %d5, %d5 " );
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "ld.w %d0, [%a2+] " ); \
|
||||
asm( "madd.u %e2, %e4, %d0, %d1 " ); \
|
||||
asm( "ld.w %d0, [%a3] " ); \
|
||||
asm( "addx %d2, %d2, %d0 " ); \
|
||||
asm( "addc %d3, %d3, 0 " ); \
|
||||
asm( "mov %d4, %d3 " ); \
|
||||
asm( "st.w [%a3+], %d2 " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "st.w %0, %%d4 " : "=m" (c)); \
|
||||
asm( "st.a %0, %%a3 " : "=m" (d)); \
|
||||
asm( "st.a %0, %%a2 " : "=m" (s) :: \
|
||||
"d0", "d1", "e2", "d4", "a2", "a3" );
|
||||
|
||||
#endif /* TriCore */
|
||||
|
||||
#if defined(__arm__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "ldr r0, %0 " :: "m" (s)); \
|
||||
asm( "ldr r1, %0 " :: "m" (d)); \
|
||||
asm( "ldr r2, %0 " :: "m" (c)); \
|
||||
asm( "ldr r3, %0 " :: "m" (b));
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "ldr r4, [r0], #4 " ); \
|
||||
asm( "mov r5, #0 " ); \
|
||||
asm( "ldr r6, [r1] " ); \
|
||||
asm( "umlal r2, r5, r3, r4 " ); \
|
||||
asm( "adds r7, r6, r2 " ); \
|
||||
asm( "adc r2, r5, #0 " ); \
|
||||
asm( "str r7, [r1], #4 " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "str r2, %0 " : "=m" (c)); \
|
||||
asm( "str r1, %0 " : "=m" (d)); \
|
||||
asm( "str r0, %0 " : "=m" (s) :: \
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
|
||||
|
||||
#endif /* ARMv3 */
|
||||
|
||||
#if defined(__alpha__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "ldq $1, %0 " :: "m" (s)); \
|
||||
asm( "ldq $2, %0 " :: "m" (d)); \
|
||||
asm( "ldq $3, %0 " :: "m" (c)); \
|
||||
asm( "ldq $4, %0 " :: "m" (b));
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "ldq $6, 0($1) " ); \
|
||||
asm( "addq $1, 8, $1 " ); \
|
||||
asm( "mulq $6, $4, $7 " ); \
|
||||
asm( "umulh $6, $4, $6 " ); \
|
||||
asm( "addq $7, $3, $7 " ); \
|
||||
asm( "cmpult $7, $3, $3 " ); \
|
||||
asm( "ldq $5, 0($2) " ); \
|
||||
asm( "addq $7, $5, $7 " ); \
|
||||
asm( "cmpult $7, $5, $5 " ); \
|
||||
asm( "stq $7, 0($2) " ); \
|
||||
asm( "addq $2, 8, $2 " ); \
|
||||
asm( "addq $6, $3, $3 " ); \
|
||||
asm( "addq $5, $3, $3 " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "stq $3, %0 " : "=m" (c)); \
|
||||
asm( "stq $2, %0 " : "=m" (d)); \
|
||||
asm( "stq $1, %0 " : "=m" (s) :: \
|
||||
"$1", "$2", "$3", "$4", "$5", "$6", "$7" );
|
||||
|
||||
#endif /* Alpha */
|
||||
|
||||
#if defined(__mips__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "lw $10, %0 " :: "m" (s)); \
|
||||
asm( "lw $11, %0 " :: "m" (d)); \
|
||||
asm( "lw $12, %0 " :: "m" (c)); \
|
||||
asm( "lw $13, %0 " :: "m" (b));
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "lw $14, 0($10) " ); \
|
||||
asm( "multu $13, $14 " ); \
|
||||
asm( "addi $10, $10, 4 " ); \
|
||||
asm( "mflo $14 " ); \
|
||||
asm( "mfhi $9 " ); \
|
||||
asm( "addu $14, $12, $14 " ); \
|
||||
asm( "lw $15, 0($11) " ); \
|
||||
asm( "sltu $12, $14, $12 " ); \
|
||||
asm( "addu $15, $14, $15 " ); \
|
||||
asm( "sltu $14, $15, $14 " ); \
|
||||
asm( "addu $12, $12, $9 " ); \
|
||||
asm( "sw $15, 0($11) " ); \
|
||||
asm( "addu $12, $12, $14 " ); \
|
||||
asm( "addi $11, $11, 4 " );
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "sw $12, %0 " : "=m" (c)); \
|
||||
asm( "sw $11, %0 " : "=m" (d)); \
|
||||
asm( "sw $10, %0 " : "=m" (s) :: \
|
||||
"$9", "$10", "$11", "$12", "$13", "$14", "$15" );
|
||||
|
||||
#endif /* MIPS */
|
||||
#endif /* GNUC */
|
||||
|
||||
#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
__asm mov esi, s \
|
||||
__asm mov edi, d \
|
||||
__asm mov ecx, c \
|
||||
__asm mov ebx, b
|
||||
|
||||
#define MULADDC_CORE \
|
||||
__asm lodsd \
|
||||
__asm mul ebx \
|
||||
__asm add eax, ecx \
|
||||
__asm adc edx, 0 \
|
||||
__asm add eax, [edi] \
|
||||
__asm adc edx, 0 \
|
||||
__asm mov ecx, edx \
|
||||
__asm stosd
|
||||
|
||||
#if defined(POLARSSL_HAVE_SSE2)
|
||||
|
||||
#define EMIT __asm _emit
|
||||
|
||||
#define MULADDC_HUIT \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x1F \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x16 \
|
||||
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
|
||||
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
|
||||
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
|
||||
EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
|
||||
EMIT 0x0F EMIT 0x7E EMIT 0x0F \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
|
||||
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
|
||||
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
|
||||
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
|
||||
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
|
||||
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
|
||||
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
|
||||
EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
|
||||
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
|
||||
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
|
||||
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
|
||||
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
|
||||
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
|
||||
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
|
||||
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
|
||||
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
|
||||
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
|
||||
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
|
||||
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
|
||||
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
|
||||
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
|
||||
EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
|
||||
EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
|
||||
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
|
||||
EMIT 0x0F EMIT 0x7E EMIT 0xC9
|
||||
|
||||
#define MULADDC_STOP \
|
||||
EMIT 0x0F EMIT 0x77 \
|
||||
__asm mov c, ecx \
|
||||
__asm mov d, edi \
|
||||
__asm mov s, esi \
|
||||
|
||||
#else
|
||||
|
||||
#define MULADDC_STOP \
|
||||
__asm mov c, ecx \
|
||||
__asm mov d, edi \
|
||||
__asm mov s, esi \
|
||||
|
||||
#endif /* SSE2 */
|
||||
#endif /* MSVC */
|
||||
|
||||
#endif /* POLARSSL_HAVE_ASM */
|
||||
|
||||
#if !defined(MULADDC_CORE)
|
||||
#if defined(POLARSSL_HAVE_LONGLONG)
|
||||
|
||||
#define MULADDC_INIT \
|
||||
{ \
|
||||
t_dbl r; \
|
||||
t_int r0, r1;
|
||||
|
||||
#define MULADDC_CORE \
|
||||
r = *(s++) * (t_dbl) b; \
|
||||
r0 = r; \
|
||||
r1 = r >> biL; \
|
||||
r0 += c; r1 += (r0 < c); \
|
||||
r0 += *d; r1 += (r0 < *d); \
|
||||
c = r1; *(d++) = r0;
|
||||
|
||||
#define MULADDC_STOP \
|
||||
}
|
||||
|
||||
#else
|
||||
#define MULADDC_INIT \
|
||||
{ \
|
||||
t_int s0, s1, b0, b1; \
|
||||
t_int r0, r1, rx, ry; \
|
||||
b0 = ( b << biH ) >> biH; \
|
||||
b1 = ( b >> biH );
|
||||
|
||||
#define MULADDC_CORE \
|
||||
s0 = ( *s << biH ) >> biH; \
|
||||
s1 = ( *s >> biH ); s++; \
|
||||
rx = s0 * b1; r0 = s0 * b0; \
|
||||
ry = s1 * b0; r1 = s1 * b1; \
|
||||
r1 += ( rx >> biH ); \
|
||||
r1 += ( ry >> biH ); \
|
||||
rx <<= biH; ry <<= biH; \
|
||||
r0 += rx; r1 += (r0 < rx); \
|
||||
r0 += ry; r1 += (r0 < ry); \
|
||||
r0 += c; r1 += (r0 < c); \
|
||||
r0 += *d; r1 += (r0 < *d); \
|
||||
c = r1; *(d++) = r0;
|
||||
|
||||
#define MULADDC_STOP \
|
||||
}
|
||||
|
||||
#endif /* C (generic) */
|
||||
#endif /* C (longlong) */
|
||||
|
||||
#endif /* bn_mul.h */
|
336
polarssl/config.h
Normal file
336
polarssl/config.h
Normal file
@ -0,0 +1,336 @@
|
||||
/**
|
||||
* \file config.h
|
||||
*
|
||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* This set of compile-time options may be used to enable
|
||||
* or disable features selectively, and reduce the global
|
||||
* memory footprint.
|
||||
*/
|
||||
#ifndef POLARSSL_CONFIG_H
|
||||
#define POLARSSL_CONFIG_H
|
||||
|
||||
#ifndef _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Uncomment if native integers are 8-bit wide.
|
||||
*
|
||||
#define POLARSSL_HAVE_INT8
|
||||
*/
|
||||
|
||||
/*
|
||||
* Uncomment if native integers are 16-bit wide.
|
||||
*
|
||||
#define POLARSSL_HAVE_INT16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Uncomment if the compiler supports long long.
|
||||
*
|
||||
#define POLARSSL_HAVE_LONGLONG
|
||||
*/
|
||||
|
||||
/*
|
||||
* Uncomment to enable the use of assembly code.
|
||||
*
|
||||
* Requires support for asm() in compiler.
|
||||
*
|
||||
* Used in:
|
||||
* library/timing.c
|
||||
* library/padlock.c
|
||||
* include/polarssl/bn_mul.h
|
||||
*
|
||||
*/
|
||||
//#define POLARSSL_HAVE_ASM
|
||||
|
||||
/*
|
||||
* Uncomment if the CPU supports SSE2 (IA-32 specific).
|
||||
*
|
||||
#define POLARSSL_HAVE_SSE2
|
||||
*/
|
||||
|
||||
/*
|
||||
* Enable all SSL/TLS debugging messages.
|
||||
*/
|
||||
#define POLARSSL_DEBUG_MSG
|
||||
|
||||
/*
|
||||
* Enable the checkup functions (*_self_test).
|
||||
*/
|
||||
//#define POLARSSL_SELF_TEST
|
||||
|
||||
/*
|
||||
* Enable run-time version information functions
|
||||
*/
|
||||
#define POLARSSL_VERSION_C
|
||||
|
||||
/*
|
||||
* Enable the prime-number generation code.
|
||||
*/
|
||||
#define POLARSSL_GENPRIME
|
||||
|
||||
/*
|
||||
* Uncomment this macro to store the AES tables in ROM.
|
||||
*
|
||||
#define POLARSSL_AES_ROM_TABLES
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module: library/aes.c
|
||||
* Caller: library/ssl_tls.c
|
||||
*
|
||||
* This module enables the following ciphersuites:
|
||||
* SSL_RSA_AES_128_SHA
|
||||
* SSL_RSA_AES_256_SHA
|
||||
* SSL_EDH_RSA_AES_256_SHA
|
||||
*/
|
||||
#define POLARSSL_AES_C
|
||||
|
||||
/*
|
||||
* Module: library/arc4.c
|
||||
* Caller: library/ssl_tls.c
|
||||
*
|
||||
* This module enables the following ciphersuites:
|
||||
* SSL_RSA_RC4_128_MD5
|
||||
* SSL_RSA_RC4_128_SHA
|
||||
*/
|
||||
#define POLARSSL_ARC4_C
|
||||
|
||||
/*
|
||||
* Module: library/base64.c
|
||||
* Caller: library/x509parse.c
|
||||
*
|
||||
* This module is required for X.509 support.
|
||||
*/
|
||||
#define POLARSSL_BASE64_C
|
||||
|
||||
/*
|
||||
* Module: library/bignum.c
|
||||
* Caller: library/dhm.c
|
||||
* library/rsa.c
|
||||
* library/ssl_tls.c
|
||||
* library/x509parse.c
|
||||
*
|
||||
* This module is required for RSA and DHM support.
|
||||
*/
|
||||
#define POLARSSL_BIGNUM_C
|
||||
|
||||
/*
|
||||
* Module: library/camellia.c
|
||||
* Caller: library/ssl_tls.c
|
||||
*
|
||||
* This module enabled the following cipher suites:
|
||||
* SSL_RSA_CAMELLIA_128_SHA
|
||||
* SSL_RSA_CAMELLIA_256_SHA
|
||||
* SSL_EDH_RSA_CAMELLIA_256_SHA
|
||||
*/
|
||||
#define POLARSSL_CAMELLIA_C
|
||||
|
||||
/*
|
||||
* Module: library/certs.c
|
||||
* Caller:
|
||||
*
|
||||
* This module is used for testing (ssl_client/server).
|
||||
*/
|
||||
#define POLARSSL_CERTS_C
|
||||
|
||||
/*
|
||||
* Module: library/debug.c
|
||||
* Caller: library/ssl_cli.c
|
||||
* library/ssl_srv.c
|
||||
* library/ssl_tls.c
|
||||
*
|
||||
* This module provides debugging functions.
|
||||
*/
|
||||
#define POLARSSL_DEBUG_C
|
||||
|
||||
/*
|
||||
* Module: library/des.c
|
||||
* Caller: library/ssl_tls.c
|
||||
*
|
||||
* This module enables the following ciphersuites:
|
||||
* SSL_RSA_DES_168_SHA
|
||||
* SSL_EDH_RSA_DES_168_SHA
|
||||
*/
|
||||
#define POLARSSL_DES_C
|
||||
|
||||
/*
|
||||
* Module: library/dhm.c
|
||||
* Caller: library/ssl_cli.c
|
||||
* library/ssl_srv.c
|
||||
*
|
||||
* This module enables the following ciphersuites:
|
||||
* SSL_EDH_RSA_DES_168_SHA
|
||||
* SSL_EDH_RSA_AES_256_SHA
|
||||
* SSL_EDH_RSA_CAMELLIA_256_SHA
|
||||
*/
|
||||
#define POLARSSL_DHM_C
|
||||
|
||||
/*
|
||||
* Module: library/havege.c
|
||||
* Caller:
|
||||
*
|
||||
* This module enables the HAVEGE random number generator.
|
||||
*/
|
||||
#define POLARSSL_HAVEGE_C
|
||||
|
||||
/*
|
||||
* Module: library/md2.c
|
||||
* Caller: library/x509parse.c
|
||||
*
|
||||
* Uncomment to enable support for (rare) MD2-signed X.509 certs.
|
||||
*
|
||||
#define POLARSSL_MD2_C
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module: library/md4.c
|
||||
* Caller: library/x509parse.c
|
||||
*
|
||||
* Uncomment to enable support for (rare) MD4-signed X.509 certs.
|
||||
*
|
||||
#define POLARSSL_MD4_C
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module: library/md5.c
|
||||
* Caller: library/ssl_tls.c
|
||||
* library/x509parse.c
|
||||
*
|
||||
* This module is required for SSL/TLS and X.509.
|
||||
*/
|
||||
#define POLARSSL_MD5_C
|
||||
|
||||
/*
|
||||
* Module: library/net.c
|
||||
* Caller:
|
||||
*
|
||||
* This module provides TCP/IP networking routines.
|
||||
*/
|
||||
#define POLARSSL_NET_C
|
||||
|
||||
/*
|
||||
* Module: library/padlock.c
|
||||
* Caller: library/aes.c
|
||||
*
|
||||
* This modules adds support for the VIA PadLock on x86.
|
||||
*/
|
||||
#define POLARSSL_PADLOCK_C
|
||||
|
||||
/*
|
||||
* Module: library/rsa.c
|
||||
* Caller: library/ssl_cli.c
|
||||
* library/ssl_srv.c
|
||||
* library/ssl_tls.c
|
||||
* library/x509.c
|
||||
*
|
||||
* This module is required for SSL/TLS and MD5-signed certificates.
|
||||
*/
|
||||
#define POLARSSL_RSA_C
|
||||
|
||||
/*
|
||||
* Module: library/sha1.c
|
||||
* Caller: library/ssl_cli.c
|
||||
* library/ssl_srv.c
|
||||
* library/ssl_tls.c
|
||||
* library/x509parse.c
|
||||
*
|
||||
* This module is required for SSL/TLS and SHA1-signed certificates.
|
||||
*/
|
||||
#define POLARSSL_SHA1_C
|
||||
|
||||
/*
|
||||
* Module: library/sha2.c
|
||||
* Caller:
|
||||
*
|
||||
* This module adds support for SHA-224 and SHA-256.
|
||||
*/
|
||||
#define POLARSSL_SHA2_C
|
||||
|
||||
/*
|
||||
* Module: library/sha4.c
|
||||
* Caller:
|
||||
*
|
||||
* This module adds support for SHA-384 and SHA-512.
|
||||
*/
|
||||
#define POLARSSL_SHA4_C
|
||||
|
||||
/*
|
||||
* Module: library/ssl_cli.c
|
||||
* Caller:
|
||||
*
|
||||
* This module is required for SSL/TLS client support.
|
||||
*/
|
||||
#define POLARSSL_SSL_CLI_C
|
||||
|
||||
/*
|
||||
* Module: library/ssl_srv.c
|
||||
* Caller:
|
||||
*
|
||||
* This module is required for SSL/TLS server support.
|
||||
*/
|
||||
#define POLARSSL_SSL_SRV_C
|
||||
|
||||
/*
|
||||
* Module: library/ssl_tls.c
|
||||
* Caller: library/ssl_cli.c
|
||||
* library/ssl_srv.c
|
||||
*
|
||||
* This module is required for SSL/TLS.
|
||||
*/
|
||||
#define POLARSSL_SSL_TLS_C
|
||||
|
||||
/*
|
||||
* Module: library/timing.c
|
||||
* Caller: library/havege.c
|
||||
*
|
||||
* This module is used by the HAVEGE random number generator.
|
||||
*/
|
||||
#define POLARSSL_TIMING_C
|
||||
|
||||
/*
|
||||
* Module: library/x509parse.c
|
||||
* Caller: library/ssl_cli.c
|
||||
* library/ssl_srv.c
|
||||
* library/ssl_tls.c
|
||||
*
|
||||
* This module is required for X.509 certificate parsing.
|
||||
*/
|
||||
#define POLARSSL_X509_PARSE_C
|
||||
|
||||
/*
|
||||
* Module: library/x509_write.c
|
||||
* Caller:
|
||||
*
|
||||
* This module is required for X.509 certificate writing.
|
||||
*/
|
||||
#define POLARSSL_X509_WRITE_C
|
||||
|
||||
/*
|
||||
* Module: library/xtea.c
|
||||
* Caller:
|
||||
*/
|
||||
#define POLARSSL_XTEA_C
|
||||
|
||||
#endif /* config.h */
|
98
polarssl/padlock.h
Normal file
98
polarssl/padlock.h
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* \file padlock.h
|
||||
*
|
||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef POLARSSL_PADLOCK_H
|
||||
#define POLARSSL_PADLOCK_H
|
||||
|
||||
#include "polarssl/aes.h"
|
||||
|
||||
#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
#ifndef POLARSSL_HAVE_X86
|
||||
#define POLARSSL_HAVE_X86
|
||||
#endif
|
||||
|
||||
#define PADLOCK_RNG 0x000C
|
||||
#define PADLOCK_ACE 0x00C0
|
||||
#define PADLOCK_PHE 0x0C00
|
||||
#define PADLOCK_PMM 0x3000
|
||||
|
||||
#define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15))
|
||||
|
||||
#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x08E0
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief PadLock detection routine
|
||||
*
|
||||
* \param The feature to detect
|
||||
*
|
||||
* \return 1 if CPU has support for the feature, 0 otherwise
|
||||
*/
|
||||
int padlock_supports( int feature );
|
||||
|
||||
/**
|
||||
* \brief PadLock AES-ECB block en(de)cryption
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param input 16-byte input block
|
||||
* \param output 16-byte output block
|
||||
*
|
||||
* \return 0 if success, 1 if operation failed
|
||||
*/
|
||||
int padlock_xcryptecb( aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
/**
|
||||
* \brief PadLock AES-CBC buffer en(de)cryption
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if success, 1 if operation failed
|
||||
*/
|
||||
int padlock_xcryptcbc( aes_context *ctx,
|
||||
int mode,
|
||||
int length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_X86 */
|
||||
|
||||
#endif /* padlock.h */
|
823
polarssl/rsa.c
Normal file
823
polarssl/rsa.c
Normal file
@ -0,0 +1,823 @@
|
||||
/*
|
||||
* The RSA public-key cryptosystem
|
||||
*
|
||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/*
|
||||
* RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
|
||||
*
|
||||
* http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
|
||||
* http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
|
||||
*/
|
||||
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#if defined(POLARSSL_RSA_C)
|
||||
|
||||
#include "polarssl/rsa.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Initialize an RSA context
|
||||
*/
|
||||
void rsa_init( rsa_context *ctx,
|
||||
int padding,
|
||||
int hash_id )
|
||||
{
|
||||
memset( ctx, 0, sizeof( rsa_context ) );
|
||||
|
||||
ctx->padding = padding;
|
||||
ctx->hash_id = hash_id;
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_GENPRIME)
|
||||
|
||||
/*
|
||||
* Generate an RSA keypair
|
||||
*/
|
||||
int rsa_gen_key( rsa_context *ctx,
|
||||
int (*f_rng)(void *),
|
||||
void *p_rng,
|
||||
int nbits, int exponent )
|
||||
{
|
||||
int ret;
|
||||
mpi P1, Q1, H, G;
|
||||
|
||||
if( f_rng == NULL || nbits < 128 || exponent < 3 )
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
mpi_init( &P1, &Q1, &H, &G, NULL );
|
||||
|
||||
/*
|
||||
* find primes P and Q with Q < P so that:
|
||||
* GCD( E, (P-1)*(Q-1) ) == 1
|
||||
*/
|
||||
MPI_CHK( mpi_lset( &ctx->E, exponent ) );
|
||||
|
||||
do
|
||||
{
|
||||
MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
|
||||
f_rng, p_rng ) );
|
||||
|
||||
MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
|
||||
f_rng, p_rng ) );
|
||||
|
||||
if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
|
||||
mpi_swap( &ctx->P, &ctx->Q );
|
||||
|
||||
if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
|
||||
continue;
|
||||
|
||||
MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
|
||||
if( mpi_msb( &ctx->N ) != nbits )
|
||||
continue;
|
||||
|
||||
MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
|
||||
MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
|
||||
MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
|
||||
MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
|
||||
}
|
||||
while( mpi_cmp_int( &G, 1 ) != 0 );
|
||||
|
||||
/*
|
||||
* D = E^-1 mod ((P-1)*(Q-1))
|
||||
* DP = D mod (P - 1)
|
||||
* DQ = D mod (Q - 1)
|
||||
* QP = Q^-1 mod P
|
||||
*/
|
||||
MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
|
||||
MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
|
||||
MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
|
||||
MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
|
||||
|
||||
ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
|
||||
|
||||
cleanup:
|
||||
|
||||
mpi_free( &G, &H, &Q1, &P1, NULL );
|
||||
|
||||
if( ret != 0 )
|
||||
{
|
||||
rsa_free( ctx );
|
||||
return( POLARSSL_ERR_RSA_KEY_GEN_FAILED | ret );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check a public RSA key
|
||||
*/
|
||||
int rsa_check_pubkey( const rsa_context *ctx )
|
||||
{
|
||||
if( !ctx->N.p || !ctx->E.p )
|
||||
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
|
||||
|
||||
if( ( ctx->N.p[0] & 1 ) == 0 ||
|
||||
( ctx->E.p[0] & 1 ) == 0 )
|
||||
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
|
||||
|
||||
if( mpi_msb( &ctx->N ) < 128 ||
|
||||
mpi_msb( &ctx->N ) > 4096 )
|
||||
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
|
||||
|
||||
if( mpi_msb( &ctx->E ) < 2 ||
|
||||
mpi_msb( &ctx->E ) > 64 )
|
||||
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a private RSA key
|
||||
*/
|
||||
int rsa_check_privkey( const rsa_context *ctx )
|
||||
{
|
||||
int ret;
|
||||
mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2;
|
||||
|
||||
if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
|
||||
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
|
||||
|
||||
mpi_init( &PQ, &DE, &P1, &Q1, &H, &I, &G, &G2, &L1, &L2, NULL );
|
||||
|
||||
MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
|
||||
MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
|
||||
MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
|
||||
MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
|
||||
MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
|
||||
MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
|
||||
|
||||
MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) );
|
||||
MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) );
|
||||
MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) );
|
||||
|
||||
/*
|
||||
* Check for a valid PKCS1v2 private key
|
||||
*/
|
||||
if( mpi_cmp_mpi( &PQ, &ctx->N ) == 0 &&
|
||||
mpi_cmp_int( &L2, 0 ) == 0 &&
|
||||
mpi_cmp_int( &I, 1 ) == 0 &&
|
||||
mpi_cmp_int( &G, 1 ) == 0 )
|
||||
{
|
||||
mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL );
|
||||
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED | ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Do an RSA public key operation
|
||||
*/
|
||||
int rsa_public( rsa_context *ctx,
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int ret, olen;
|
||||
mpi T;
|
||||
|
||||
mpi_init( &T, NULL );
|
||||
|
||||
MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
|
||||
|
||||
if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
|
||||
{
|
||||
mpi_free( &T, NULL );
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
olen = ctx->len;
|
||||
MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
|
||||
MPI_CHK( mpi_write_binary( &T, output, olen ) );
|
||||
|
||||
cleanup:
|
||||
|
||||
mpi_free( &T, NULL );
|
||||
|
||||
if( ret != 0 )
|
||||
return( POLARSSL_ERR_RSA_PUBLIC_FAILED | ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Do an RSA private key operation
|
||||
*/
|
||||
int rsa_private( rsa_context *ctx,
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int ret, olen;
|
||||
mpi T, T1, T2;
|
||||
|
||||
mpi_init( &T, &T1, &T2, NULL );
|
||||
|
||||
MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
|
||||
|
||||
if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
|
||||
{
|
||||
mpi_free( &T, NULL );
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
#if 0
|
||||
MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
|
||||
#else
|
||||
/*
|
||||
* faster decryption using the CRT
|
||||
*
|
||||
* T1 = input ^ dP mod P
|
||||
* T2 = input ^ dQ mod Q
|
||||
*/
|
||||
MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
|
||||
MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
|
||||
|
||||
/*
|
||||
* T = (T1 - T2) * (Q^-1 mod P) mod P
|
||||
*/
|
||||
MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
|
||||
MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
|
||||
MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
|
||||
|
||||
/*
|
||||
* output = T2 + T * Q
|
||||
*/
|
||||
MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
|
||||
MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
|
||||
#endif
|
||||
|
||||
olen = ctx->len;
|
||||
MPI_CHK( mpi_write_binary( &T, output, olen ) );
|
||||
|
||||
cleanup:
|
||||
|
||||
mpi_free( &T, &T1, &T2, NULL );
|
||||
|
||||
if( ret != 0 )
|
||||
return( POLARSSL_ERR_RSA_PRIVATE_FAILED | ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the message padding, then do an RSA operation
|
||||
*/
|
||||
int rsa_pkcs1_encrypt( rsa_context *ctx,
|
||||
int (*f_rng)(void *),
|
||||
void *p_rng,
|
||||
int mode, int ilen,
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int nb_pad, olen;
|
||||
unsigned char *p = output;
|
||||
|
||||
olen = ctx->len;
|
||||
|
||||
switch( ctx->padding )
|
||||
{
|
||||
case RSA_PKCS_V15:
|
||||
|
||||
if( ilen < 0 || olen < ilen + 11 || f_rng == NULL )
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
nb_pad = olen - 3 - ilen;
|
||||
|
||||
*p++ = 0;
|
||||
*p++ = RSA_CRYPT;
|
||||
|
||||
while( nb_pad-- > 0 )
|
||||
{
|
||||
int rng_dl = 100;
|
||||
|
||||
do {
|
||||
*p = (unsigned char) f_rng( p_rng );
|
||||
} while( *p == 0 && --rng_dl );
|
||||
|
||||
// Check if RNG failed to generate data
|
||||
//
|
||||
if( rng_dl == 0 )
|
||||
return POLARSSL_ERR_RSA_RNG_FAILED;
|
||||
|
||||
p++;
|
||||
}
|
||||
*p++ = 0;
|
||||
memcpy( p, input, ilen );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
return( POLARSSL_ERR_RSA_INVALID_PADDING );
|
||||
}
|
||||
|
||||
return( ( mode == RSA_PUBLIC )
|
||||
? rsa_public( ctx, output, output )
|
||||
: rsa_private( ctx, output, output ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Do an RSA operation, then remove the message padding
|
||||
*/
|
||||
int rsa_pkcs1_decrypt( rsa_context *ctx,
|
||||
int mode, int *olen,
|
||||
const unsigned char *input,
|
||||
unsigned char *output,
|
||||
int output_max_len)
|
||||
{
|
||||
int ret, ilen;
|
||||
unsigned char *p;
|
||||
unsigned char buf[1024];
|
||||
|
||||
ilen = ctx->len;
|
||||
|
||||
if( ilen < 16 || ilen > (int) sizeof( buf ) )
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
ret = ( mode == RSA_PUBLIC )
|
||||
? rsa_public( ctx, input, buf )
|
||||
: rsa_private( ctx, input, buf );
|
||||
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
p = buf;
|
||||
|
||||
switch( ctx->padding )
|
||||
{
|
||||
case RSA_PKCS_V15:
|
||||
|
||||
if( *p++ != 0 || *p++ != RSA_CRYPT )
|
||||
return( POLARSSL_ERR_RSA_INVALID_PADDING );
|
||||
|
||||
while( *p != 0 )
|
||||
{
|
||||
if( p >= buf + ilen - 1 )
|
||||
return( POLARSSL_ERR_RSA_INVALID_PADDING );
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
return( POLARSSL_ERR_RSA_INVALID_PADDING );
|
||||
}
|
||||
|
||||
if (ilen - (int)(p - buf) > output_max_len)
|
||||
return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
|
||||
|
||||
*olen = ilen - (int)(p - buf);
|
||||
memcpy( output, p, *olen );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Do an RSA operation to sign the message digest
|
||||
*/
|
||||
int rsa_pkcs1_sign( rsa_context *ctx,
|
||||
int mode,
|
||||
int hash_id,
|
||||
int hashlen,
|
||||
const unsigned char *hash,
|
||||
unsigned char *sig )
|
||||
{
|
||||
int nb_pad, olen;
|
||||
unsigned char *p = sig;
|
||||
|
||||
olen = ctx->len;
|
||||
|
||||
switch( ctx->padding )
|
||||
{
|
||||
case RSA_PKCS_V15:
|
||||
|
||||
switch( hash_id )
|
||||
{
|
||||
case SIG_RSA_RAW:
|
||||
nb_pad = olen - 3 - hashlen;
|
||||
break;
|
||||
|
||||
case SIG_RSA_MD2:
|
||||
case SIG_RSA_MD4:
|
||||
case SIG_RSA_MD5:
|
||||
nb_pad = olen - 3 - 34;
|
||||
break;
|
||||
|
||||
case SIG_RSA_SHA1:
|
||||
nb_pad = olen - 3 - 35;
|
||||
break;
|
||||
|
||||
case SIG_RSA_SHA224:
|
||||
nb_pad = olen - 3 - 47;
|
||||
break;
|
||||
|
||||
case SIG_RSA_SHA256:
|
||||
nb_pad = olen - 3 - 51;
|
||||
break;
|
||||
|
||||
case SIG_RSA_SHA384:
|
||||
nb_pad = olen - 3 - 67;
|
||||
break;
|
||||
|
||||
case SIG_RSA_SHA512:
|
||||
nb_pad = olen - 3 - 83;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
if( nb_pad < 8 )
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
*p++ = 0;
|
||||
*p++ = RSA_SIGN;
|
||||
memset( p, 0xFF, nb_pad );
|
||||
p += nb_pad;
|
||||
*p++ = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
return( POLARSSL_ERR_RSA_INVALID_PADDING );
|
||||
}
|
||||
|
||||
switch( hash_id )
|
||||
{
|
||||
case SIG_RSA_RAW:
|
||||
memcpy( p, hash, hashlen );
|
||||
break;
|
||||
|
||||
case SIG_RSA_MD2:
|
||||
memcpy( p, ASN1_HASH_MDX, 18 );
|
||||
memcpy( p + 18, hash, 16 );
|
||||
p[13] = 2; break;
|
||||
|
||||
case SIG_RSA_MD4:
|
||||
memcpy( p, ASN1_HASH_MDX, 18 );
|
||||
memcpy( p + 18, hash, 16 );
|
||||
p[13] = 4; break;
|
||||
|
||||
case SIG_RSA_MD5:
|
||||
memcpy( p, ASN1_HASH_MDX, 18 );
|
||||
memcpy( p + 18, hash, 16 );
|
||||
p[13] = 5; break;
|
||||
|
||||
case SIG_RSA_SHA1:
|
||||
memcpy( p, ASN1_HASH_SHA1, 15 );
|
||||
memcpy( p + 15, hash, 20 );
|
||||
break;
|
||||
|
||||
case SIG_RSA_SHA224:
|
||||
memcpy( p, ASN1_HASH_SHA2X, 19 );
|
||||
memcpy( p + 19, hash, 28 );
|
||||
p[1] += 28; p[14] = 4; p[18] += 28; break;
|
||||
|
||||
case SIG_RSA_SHA256:
|
||||
memcpy( p, ASN1_HASH_SHA2X, 19 );
|
||||
memcpy( p + 19, hash, 32 );
|
||||
p[1] += 32; p[14] = 1; p[18] += 32; break;
|
||||
|
||||
case SIG_RSA_SHA384:
|
||||
memcpy( p, ASN1_HASH_SHA2X, 19 );
|
||||
memcpy( p + 19, hash, 48 );
|
||||
p[1] += 48; p[14] = 2; p[18] += 48; break;
|
||||
|
||||
case SIG_RSA_SHA512:
|
||||
memcpy( p, ASN1_HASH_SHA2X, 19 );
|
||||
memcpy( p + 19, hash, 64 );
|
||||
p[1] += 64; p[14] = 3; p[18] += 64; break;
|
||||
|
||||
default:
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
return( ( mode == RSA_PUBLIC )
|
||||
? rsa_public( ctx, sig, sig )
|
||||
: rsa_private( ctx, sig, sig ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Do an RSA operation and check the message digest
|
||||
*/
|
||||
int rsa_pkcs1_verify( rsa_context *ctx,
|
||||
int mode,
|
||||
int hash_id,
|
||||
int hashlen,
|
||||
const unsigned char *hash,
|
||||
unsigned char *sig )
|
||||
{
|
||||
int ret, len, siglen;
|
||||
unsigned char *p, c;
|
||||
unsigned char buf[1024];
|
||||
|
||||
siglen = ctx->len;
|
||||
|
||||
if( siglen < 16 || siglen > (int) sizeof( buf ) )
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
ret = ( mode == RSA_PUBLIC )
|
||||
? rsa_public( ctx, sig, buf )
|
||||
: rsa_private( ctx, sig, buf );
|
||||
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
p = buf;
|
||||
|
||||
switch( ctx->padding )
|
||||
{
|
||||
case RSA_PKCS_V15:
|
||||
|
||||
if( *p++ != 0 || *p++ != RSA_SIGN )
|
||||
return( POLARSSL_ERR_RSA_INVALID_PADDING );
|
||||
|
||||
while( *p != 0 )
|
||||
{
|
||||
if( p >= buf + siglen - 1 || *p != 0xFF )
|
||||
return( POLARSSL_ERR_RSA_INVALID_PADDING );
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
return( POLARSSL_ERR_RSA_INVALID_PADDING );
|
||||
}
|
||||
|
||||
len = siglen - (int)( p - buf );
|
||||
|
||||
if( len == 34 )
|
||||
{
|
||||
c = p[13];
|
||||
p[13] = 0;
|
||||
|
||||
if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
|
||||
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
|
||||
|
||||
if( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
|
||||
( c == 4 && hash_id == SIG_RSA_MD4 ) ||
|
||||
( c == 5 && hash_id == SIG_RSA_MD5 ) )
|
||||
{
|
||||
if( memcmp( p + 18, hash, 16 ) == 0 )
|
||||
return( 0 );
|
||||
else
|
||||
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
|
||||
}
|
||||
}
|
||||
|
||||
if( len == 35 && hash_id == SIG_RSA_SHA1 )
|
||||
{
|
||||
if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
|
||||
memcmp( p + 15, hash, 20 ) == 0 )
|
||||
return( 0 );
|
||||
else
|
||||
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
|
||||
}
|
||||
if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
|
||||
( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
|
||||
( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
|
||||
( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
|
||||
{
|
||||
c = p[1] - 17;
|
||||
p[1] = 17;
|
||||
p[14] = 0;
|
||||
|
||||
if( p[18] == c &&
|
||||
memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
|
||||
memcmp( p + 19, hash, c ) == 0 )
|
||||
return( 0 );
|
||||
else
|
||||
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
|
||||
}
|
||||
|
||||
if( len == hashlen && hash_id == SIG_RSA_RAW )
|
||||
{
|
||||
if( memcmp( p, hash, hashlen ) == 0 )
|
||||
return( 0 );
|
||||
else
|
||||
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
|
||||
}
|
||||
|
||||
return( POLARSSL_ERR_RSA_INVALID_PADDING );
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the components of an RSA key
|
||||
*/
|
||||
void rsa_free( rsa_context *ctx )
|
||||
{
|
||||
mpi_free( &ctx->RQ, &ctx->RP, &ctx->RN,
|
||||
&ctx->QP, &ctx->DQ, &ctx->DP,
|
||||
&ctx->Q, &ctx->P, &ctx->D,
|
||||
&ctx->E, &ctx->N, NULL );
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_SELF_TEST)
|
||||
|
||||
#include "polarssl/sha1.h"
|
||||
|
||||
/*
|
||||
* Example RSA-1024 keypair, for test purposes
|
||||
*/
|
||||
#define KEY_LEN 128
|
||||
|
||||
#define RSA_N "9292758453063D803DD603D5E777D788" \
|
||||
"8ED1D5BF35786190FA2F23EBC0848AEA" \
|
||||
"DDA92CA6C3D80B32C4D109BE0F36D6AE" \
|
||||
"7130B9CED7ACDF54CFC7555AC14EEBAB" \
|
||||
"93A89813FBF3C4F8066D2D800F7C38A8" \
|
||||
"1AE31942917403FF4946B0A83D3D3E05" \
|
||||
"EE57C6F5F5606FB5D4BC6CD34EE0801A" \
|
||||
"5E94BB77B07507233A0BC7BAC8F90F79"
|
||||
|
||||
#define RSA_E "10001"
|
||||
|
||||
#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
|
||||
"66CA472BC44D253102F8B4A9D3BFA750" \
|
||||
"91386C0077937FE33FA3252D28855837" \
|
||||
"AE1B484A8A9A45F7EE8C0C634F99E8CD" \
|
||||
"DF79C5CE07EE72C7F123142198164234" \
|
||||
"CABB724CF78B8173B9F880FC86322407" \
|
||||
"AF1FEDFDDE2BEB674CA15F3E81A1521E" \
|
||||
"071513A1E85B5DFA031F21ECAE91A34D"
|
||||
|
||||
#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
|
||||
"2C01CAD19EA484A87EA4377637E75500" \
|
||||
"FCB2005C5C7DD6EC4AC023CDA285D796" \
|
||||
"C3D9E75E1EFC42488BB4F1D13AC30A57"
|
||||
|
||||
#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
|
||||
"E211C2B9E5DB1ED0BF61D0D9899620F4" \
|
||||
"910E4168387E3C30AA1E00C339A79508" \
|
||||
"8452DD96A9A5EA5D9DCA68DA636032AF"
|
||||
|
||||
#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
|
||||
"3C94D22288ACD763FD8E5600ED4A702D" \
|
||||
"F84198A5F06C2E72236AE490C93F07F8" \
|
||||
"3CC559CD27BC2D1CA488811730BB5725"
|
||||
|
||||
#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
|
||||
"D8AAEA56749EA28623272E4F7D0592AF" \
|
||||
"7C1F1313CAC9471B5C523BFE592F517B" \
|
||||
"407A1BD76C164B93DA2D32A383E58357"
|
||||
|
||||
#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
|
||||
"F38D18D2B2F0E2DD275AA977E2BF4411" \
|
||||
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
|
||||
"A74206CEC169D74BF5A8C50D6F48EA08"
|
||||
|
||||
#define PT_LEN 24
|
||||
#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
|
||||
"\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
|
||||
|
||||
static int myrand( void *rng_state )
|
||||
{
|
||||
if( rng_state != NULL )
|
||||
rng_state = NULL;
|
||||
|
||||
return( rand() );
|
||||
}
|
||||
|
||||
/*
|
||||
* Checkup routine
|
||||
*/
|
||||
int rsa_self_test( int verbose )
|
||||
{
|
||||
int len;
|
||||
rsa_context rsa;
|
||||
unsigned char sha1sum[20];
|
||||
unsigned char rsa_plaintext[PT_LEN];
|
||||
unsigned char rsa_decrypted[PT_LEN];
|
||||
unsigned char rsa_ciphertext[KEY_LEN];
|
||||
|
||||
rsa_init( &rsa, RSA_PKCS_V15, 0 );
|
||||
|
||||
rsa.len = KEY_LEN;
|
||||
mpi_read_string( &rsa.N , 16, RSA_N );
|
||||
mpi_read_string( &rsa.E , 16, RSA_E );
|
||||
mpi_read_string( &rsa.D , 16, RSA_D );
|
||||
mpi_read_string( &rsa.P , 16, RSA_P );
|
||||
mpi_read_string( &rsa.Q , 16, RSA_Q );
|
||||
mpi_read_string( &rsa.DP, 16, RSA_DP );
|
||||
mpi_read_string( &rsa.DQ, 16, RSA_DQ );
|
||||
mpi_read_string( &rsa.QP, 16, RSA_QP );
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( " RSA key validation: " );
|
||||
|
||||
if( rsa_check_pubkey( &rsa ) != 0 ||
|
||||
rsa_check_privkey( &rsa ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "passed\n PKCS#1 encryption : " );
|
||||
|
||||
memcpy( rsa_plaintext, RSA_PT, PT_LEN );
|
||||
|
||||
if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN,
|
||||
rsa_plaintext, rsa_ciphertext ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "passed\n PKCS#1 decryption : " );
|
||||
|
||||
if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len,
|
||||
rsa_ciphertext, rsa_decrypted,
|
||||
sizeof(rsa_decrypted) ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "passed\n PKCS#1 data sign : " );
|
||||
|
||||
sha1( rsa_plaintext, PT_LEN, sha1sum );
|
||||
|
||||
if( rsa_pkcs1_sign( &rsa, RSA_PRIVATE, SIG_RSA_SHA1, 20,
|
||||
sha1sum, rsa_ciphertext ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "passed\n PKCS#1 sig. verify: " );
|
||||
|
||||
if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20,
|
||||
sha1sum, rsa_ciphertext ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "passed\n\n" );
|
||||
|
||||
rsa_free( &rsa );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
353
polarssl/rsa.h
Normal file
353
polarssl/rsa.h
Normal file
@ -0,0 +1,353 @@
|
||||
/**
|
||||
* \file rsa.h
|
||||
*
|
||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef POLARSSL_RSA_H
|
||||
#define POLARSSL_RSA_H
|
||||
|
||||
#include "polarssl/bignum.h"
|
||||
|
||||
/*
|
||||
* RSA Error codes
|
||||
*/
|
||||
#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x0400
|
||||
#define POLARSSL_ERR_RSA_INVALID_PADDING -0x0410
|
||||
#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x0420
|
||||
#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x0430
|
||||
#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x0440
|
||||
#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x0450
|
||||
#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x0460
|
||||
#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x0470
|
||||
#define POLARSSL_ERR_RSA_RNG_FAILED -0x0480
|
||||
|
||||
/*
|
||||
* PKCS#1 constants
|
||||
*/
|
||||
#define SIG_RSA_RAW 0
|
||||
#define SIG_RSA_MD2 2
|
||||
#define SIG_RSA_MD4 3
|
||||
#define SIG_RSA_MD5 4
|
||||
#define SIG_RSA_SHA1 5
|
||||
#define SIG_RSA_SHA224 14
|
||||
#define SIG_RSA_SHA256 11
|
||||
#define SIG_RSA_SHA384 12
|
||||
#define SIG_RSA_SHA512 13
|
||||
|
||||
#define RSA_PUBLIC 0
|
||||
#define RSA_PRIVATE 1
|
||||
|
||||
#define RSA_PKCS_V15 0
|
||||
#define RSA_PKCS_V21 1
|
||||
|
||||
#define RSA_SIGN 1
|
||||
#define RSA_CRYPT 2
|
||||
|
||||
#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30"
|
||||
#define ASN1_STR_NULL "\x05"
|
||||
#define ASN1_STR_OID "\x06"
|
||||
#define ASN1_STR_OCTET_STRING "\x04"
|
||||
|
||||
#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00"
|
||||
#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a"
|
||||
#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00"
|
||||
|
||||
#define OID_ISO_MEMBER_BODIES "\x2a"
|
||||
#define OID_ISO_IDENTIFIED_ORG "\x2b"
|
||||
|
||||
/*
|
||||
* ISO Member bodies OID parts
|
||||
*/
|
||||
#define OID_COUNTRY_US "\x86\x48"
|
||||
#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d"
|
||||
|
||||
/*
|
||||
* ISO Identified organization OID parts
|
||||
*/
|
||||
#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a"
|
||||
|
||||
/*
|
||||
* DigestInfo ::= SEQUENCE {
|
||||
* digestAlgorithm DigestAlgorithmIdentifier,
|
||||
* digest Digest }
|
||||
*
|
||||
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
|
||||
*
|
||||
* Digest ::= OCTET STRING
|
||||
*/
|
||||
#define ASN1_HASH_MDX \
|
||||
( \
|
||||
ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \
|
||||
ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \
|
||||
ASN1_STR_OID "\x08" \
|
||||
OID_DIGEST_ALG_MDX \
|
||||
ASN1_STR_NULL "\x00" \
|
||||
ASN1_STR_OCTET_STRING "\x10" \
|
||||
)
|
||||
|
||||
#define ASN1_HASH_SHA1 \
|
||||
ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \
|
||||
ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \
|
||||
ASN1_STR_OID "\x05" \
|
||||
OID_HASH_ALG_SHA1 \
|
||||
ASN1_STR_NULL "\x00" \
|
||||
ASN1_STR_OCTET_STRING "\x14"
|
||||
|
||||
#define ASN1_HASH_SHA2X \
|
||||
ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \
|
||||
ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \
|
||||
ASN1_STR_OID "\x09" \
|
||||
OID_HASH_ALG_SHA2X \
|
||||
ASN1_STR_NULL "\x00" \
|
||||
ASN1_STR_OCTET_STRING "\x00"
|
||||
|
||||
/**
|
||||
* \brief RSA context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int ver; /*!< always 0 */
|
||||
int len; /*!< size(N) in chars */
|
||||
|
||||
mpi N; /*!< public modulus */
|
||||
mpi E; /*!< public exponent */
|
||||
|
||||
mpi D; /*!< private exponent */
|
||||
mpi P; /*!< 1st prime factor */
|
||||
mpi Q; /*!< 2nd prime factor */
|
||||
mpi DP; /*!< D % (P - 1) */
|
||||
mpi DQ; /*!< D % (Q - 1) */
|
||||
mpi QP; /*!< 1 / (Q % P) */
|
||||
|
||||
mpi RN; /*!< cached R^2 mod N */
|
||||
mpi RP; /*!< cached R^2 mod P */
|
||||
mpi RQ; /*!< cached R^2 mod Q */
|
||||
|
||||
int padding; /*!< 1.5 or OAEP/PSS */
|
||||
int hash_id; /*!< hash identifier */
|
||||
}
|
||||
rsa_context;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Initialize an RSA context
|
||||
*
|
||||
* \param ctx RSA context to be initialized
|
||||
* \param padding RSA_PKCS_V15 or RSA_PKCS_V21
|
||||
* \param hash_id RSA_PKCS_V21 hash identifier
|
||||
*
|
||||
* \note The hash_id parameter is actually ignored
|
||||
* when using RSA_PKCS_V15 padding.
|
||||
*
|
||||
* \note Currently, RSA_PKCS_V21 padding
|
||||
* is not supported.
|
||||
*/
|
||||
void rsa_init( rsa_context *ctx,
|
||||
int padding,
|
||||
int hash_id);
|
||||
|
||||
/**
|
||||
* \brief Generate an RSA keypair
|
||||
*
|
||||
* \param ctx RSA context that will hold the key
|
||||
* \param f_rng RNG function
|
||||
* \param p_rng RNG parameter
|
||||
* \param nbits size of the public key in bits
|
||||
* \param exponent public exponent (e.g., 65537)
|
||||
*
|
||||
* \note rsa_init() must be called beforehand to setup
|
||||
* the RSA context.
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
|
||||
*/
|
||||
int rsa_gen_key( rsa_context *ctx,
|
||||
int (*f_rng)(void *),
|
||||
void *p_rng,
|
||||
int nbits, int exponent );
|
||||
|
||||
/**
|
||||
* \brief Check a public RSA key
|
||||
*
|
||||
* \param ctx RSA context to be checked
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
|
||||
*/
|
||||
int rsa_check_pubkey( const rsa_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Check a private RSA key
|
||||
*
|
||||
* \param ctx RSA context to be checked
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
|
||||
*/
|
||||
int rsa_check_privkey( const rsa_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Do an RSA public key operation
|
||||
*
|
||||
* \param ctx RSA context
|
||||
* \param input input buffer
|
||||
* \param output output buffer
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
|
||||
*
|
||||
* \note This function does NOT take care of message
|
||||
* padding. Also, be sure to set input[0] = 0 or assure that
|
||||
* input is smaller than N.
|
||||
*
|
||||
* \note The input and output buffers must be large
|
||||
* enough (eg. 128 bytes if RSA-1024 is used).
|
||||
*/
|
||||
int rsa_public( rsa_context *ctx,
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief Do an RSA private key operation
|
||||
*
|
||||
* \param ctx RSA context
|
||||
* \param input input buffer
|
||||
* \param output output buffer
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
|
||||
*
|
||||
* \note The input and output buffers must be large
|
||||
* enough (eg. 128 bytes if RSA-1024 is used).
|
||||
*/
|
||||
int rsa_private( rsa_context *ctx,
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief Add the message padding, then do an RSA operation
|
||||
*
|
||||
* \param ctx RSA context
|
||||
* \param f_rng RNG function
|
||||
* \param p_rng RNG parameter
|
||||
* \param mode RSA_PUBLIC or RSA_PRIVATE
|
||||
* \param ilen contains the plaintext length
|
||||
* \param input buffer holding the data to be encrypted
|
||||
* \param output buffer that will hold the ciphertext
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
|
||||
*
|
||||
* \note The output buffer must be as large as the size
|
||||
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
|
||||
*/
|
||||
int rsa_pkcs1_encrypt( rsa_context *ctx,
|
||||
int (*f_rng)(void *),
|
||||
void *p_rng,
|
||||
int mode, int ilen,
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief Do an RSA operation, then remove the message padding
|
||||
*
|
||||
* \param ctx RSA context
|
||||
* \param mode RSA_PUBLIC or RSA_PRIVATE
|
||||
* \param input buffer holding the encrypted data
|
||||
* \param output buffer that will hold the plaintext
|
||||
* \param olen will contain the plaintext length
|
||||
* \param output_max_len maximum length of the output buffer
|
||||
*
|
||||
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
|
||||
*
|
||||
* \note The output buffer must be as large as the size
|
||||
* of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
|
||||
* an error is thrown.
|
||||
*/
|
||||
int rsa_pkcs1_decrypt( rsa_context *ctx,
|
||||
int mode, int *olen,
|
||||
const unsigned char *input,
|
||||
unsigned char *output,
|
||||
int output_max_len );
|
||||
|
||||
/**
|
||||
* \brief Do a private RSA to sign a message digest
|
||||
*
|
||||
* \param ctx RSA context
|
||||
* \param mode RSA_PUBLIC or RSA_PRIVATE
|
||||
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
|
||||
* \param hashlen message digest length (for SIG_RSA_RAW only)
|
||||
* \param hash buffer holding the message digest
|
||||
* \param sig buffer that will hold the ciphertext
|
||||
*
|
||||
* \return 0 if the signing operation was successful,
|
||||
* or an POLARSSL_ERR_RSA_XXX error code
|
||||
*
|
||||
* \note The "sig" buffer must be as large as the size
|
||||
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
|
||||
*/
|
||||
int rsa_pkcs1_sign( rsa_context *ctx,
|
||||
int mode,
|
||||
int hash_id,
|
||||
int hashlen,
|
||||
const unsigned char *hash,
|
||||
unsigned char *sig );
|
||||
|
||||
/**
|
||||
* \brief Do a public RSA and check the message digest
|
||||
*
|
||||
* \param ctx points to an RSA public key
|
||||
* \param mode RSA_PUBLIC or RSA_PRIVATE
|
||||
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
|
||||
* \param hashlen message digest length (for SIG_RSA_RAW only)
|
||||
* \param hash buffer holding the message digest
|
||||
* \param sig buffer holding the ciphertext
|
||||
*
|
||||
* \return 0 if the verify operation was successful,
|
||||
* or an POLARSSL_ERR_RSA_XXX error code
|
||||
*
|
||||
* \note The "sig" buffer must be as large as the size
|
||||
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
|
||||
*/
|
||||
int rsa_pkcs1_verify( rsa_context *ctx,
|
||||
int mode,
|
||||
int hash_id,
|
||||
int hashlen,
|
||||
const unsigned char *hash,
|
||||
unsigned char *sig );
|
||||
|
||||
/**
|
||||
* \brief Free the components of an RSA key
|
||||
*
|
||||
* \param ctx RSA Context to free
|
||||
*/
|
||||
void rsa_free( rsa_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int rsa_self_test( int verbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* rsa.h */
|
702
polarssl/sha2.c
Normal file
702
polarssl/sha2.c
Normal file
@ -0,0 +1,702 @@
|
||||
/*
|
||||
* FIPS-180-2 compliant SHA-256 implementation
|
||||
*
|
||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/*
|
||||
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
|
||||
*
|
||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
*/
|
||||
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#if defined(POLARSSL_SHA2_C)
|
||||
|
||||
#include "polarssl/sha2.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef GET_ULONG_BE
|
||||
#define GET_ULONG_BE(n,b,i) \
|
||||
{ \
|
||||
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
|
||||
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
|
||||
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
|
||||
| ( (unsigned long) (b)[(i) + 3] ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PUT_ULONG_BE
|
||||
#define PUT_ULONG_BE(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SHA-256 context setup
|
||||
*/
|
||||
void sha2_starts( sha2_context *ctx, int is224 )
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
if( is224 == 0 )
|
||||
{
|
||||
/* SHA-256 */
|
||||
ctx->state[0] = 0x6A09E667;
|
||||
ctx->state[1] = 0xBB67AE85;
|
||||
ctx->state[2] = 0x3C6EF372;
|
||||
ctx->state[3] = 0xA54FF53A;
|
||||
ctx->state[4] = 0x510E527F;
|
||||
ctx->state[5] = 0x9B05688C;
|
||||
ctx->state[6] = 0x1F83D9AB;
|
||||
ctx->state[7] = 0x5BE0CD19;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SHA-224 */
|
||||
ctx->state[0] = 0xC1059ED8;
|
||||
ctx->state[1] = 0x367CD507;
|
||||
ctx->state[2] = 0x3070DD17;
|
||||
ctx->state[3] = 0xF70E5939;
|
||||
ctx->state[4] = 0xFFC00B31;
|
||||
ctx->state[5] = 0x68581511;
|
||||
ctx->state[6] = 0x64F98FA7;
|
||||
ctx->state[7] = 0xBEFA4FA4;
|
||||
}
|
||||
|
||||
ctx->is224 = is224;
|
||||
}
|
||||
|
||||
static void sha2_process( sha2_context *ctx, const unsigned char data[64] )
|
||||
{
|
||||
unsigned long temp1, temp2, W[64];
|
||||
unsigned long A, B, C, D, E, F, G, H;
|
||||
|
||||
GET_ULONG_BE( W[ 0], data, 0 );
|
||||
GET_ULONG_BE( W[ 1], data, 4 );
|
||||
GET_ULONG_BE( W[ 2], data, 8 );
|
||||
GET_ULONG_BE( W[ 3], data, 12 );
|
||||
GET_ULONG_BE( W[ 4], data, 16 );
|
||||
GET_ULONG_BE( W[ 5], data, 20 );
|
||||
GET_ULONG_BE( W[ 6], data, 24 );
|
||||
GET_ULONG_BE( W[ 7], data, 28 );
|
||||
GET_ULONG_BE( W[ 8], data, 32 );
|
||||
GET_ULONG_BE( W[ 9], data, 36 );
|
||||
GET_ULONG_BE( W[10], data, 40 );
|
||||
GET_ULONG_BE( W[11], data, 44 );
|
||||
GET_ULONG_BE( W[12], data, 48 );
|
||||
GET_ULONG_BE( W[13], data, 52 );
|
||||
GET_ULONG_BE( W[14], data, 56 );
|
||||
GET_ULONG_BE( W[15], data, 60 );
|
||||
|
||||
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
|
||||
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
|
||||
|
||||
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
|
||||
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
|
||||
|
||||
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
|
||||
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
|
||||
|
||||
#define F0(x,y,z) ((x & y) | (z & (x | y)))
|
||||
#define F1(x,y,z) (z ^ (x & (y ^ z)))
|
||||
|
||||
#define R(t) \
|
||||
( \
|
||||
W[t] = S1(W[t - 2]) + W[t - 7] + \
|
||||
S0(W[t - 15]) + W[t - 16] \
|
||||
)
|
||||
|
||||
#define P(a,b,c,d,e,f,g,h,x,K) \
|
||||
{ \
|
||||
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
|
||||
temp2 = S2(a) + F0(a,b,c); \
|
||||
d += temp1; h = temp1 + temp2; \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
E = ctx->state[4];
|
||||
F = ctx->state[5];
|
||||
G = ctx->state[6];
|
||||
H = ctx->state[7];
|
||||
|
||||
P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
|
||||
P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
|
||||
P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
|
||||
P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
|
||||
P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
|
||||
P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
|
||||
P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
|
||||
P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
|
||||
P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
|
||||
P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
|
||||
P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
|
||||
P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
|
||||
P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
|
||||
P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
|
||||
P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
|
||||
P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
|
||||
P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
|
||||
P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
|
||||
P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
|
||||
P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
|
||||
P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
|
||||
P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
|
||||
P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
|
||||
P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
|
||||
P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
|
||||
P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
|
||||
P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
|
||||
P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
|
||||
P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
|
||||
P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
|
||||
P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
|
||||
P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
|
||||
P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
|
||||
P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
|
||||
P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
|
||||
P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
|
||||
P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
|
||||
P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
|
||||
P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
|
||||
P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
|
||||
P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
|
||||
P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
|
||||
P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
|
||||
P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
|
||||
P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
|
||||
P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
|
||||
P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
|
||||
P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
|
||||
P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
|
||||
P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
|
||||
P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
|
||||
P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
|
||||
P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
|
||||
P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
|
||||
P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
|
||||
P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
|
||||
P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
|
||||
P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
|
||||
P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
|
||||
P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
|
||||
P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
|
||||
P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
|
||||
P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
|
||||
P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
ctx->state[4] += E;
|
||||
ctx->state[5] += F;
|
||||
ctx->state[6] += G;
|
||||
ctx->state[7] += H;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 process buffer
|
||||
*/
|
||||
void sha2_update( sha2_context *ctx, const unsigned char *input, int ilen )
|
||||
{
|
||||
int fill;
|
||||
unsigned long left;
|
||||
|
||||
if( ilen <= 0 )
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (unsigned long) ilen )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && ilen >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left),
|
||||
(void *) input, fill );
|
||||
sha2_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 )
|
||||
{
|
||||
sha2_process( ctx, input );
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left),
|
||||
(void *) input, ilen );
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char sha2_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-256 final digest
|
||||
*/
|
||||
void sha2_finish( sha2_context *ctx, unsigned char output[32] )
|
||||
{
|
||||
unsigned long last, padn;
|
||||
unsigned long high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_ULONG_BE( high, msglen, 0 );
|
||||
PUT_ULONG_BE( low, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
sha2_update( ctx, (unsigned char *) sha2_padding, padn );
|
||||
sha2_update( ctx, msglen, 8 );
|
||||
|
||||
PUT_ULONG_BE( ctx->state[0], output, 0 );
|
||||
PUT_ULONG_BE( ctx->state[1], output, 4 );
|
||||
PUT_ULONG_BE( ctx->state[2], output, 8 );
|
||||
PUT_ULONG_BE( ctx->state[3], output, 12 );
|
||||
PUT_ULONG_BE( ctx->state[4], output, 16 );
|
||||
PUT_ULONG_BE( ctx->state[5], output, 20 );
|
||||
PUT_ULONG_BE( ctx->state[6], output, 24 );
|
||||
|
||||
if( ctx->is224 == 0 )
|
||||
PUT_ULONG_BE( ctx->state[7], output, 28 );
|
||||
}
|
||||
|
||||
/*
|
||||
* output = SHA-256( input buffer )
|
||||
*/
|
||||
void sha2( const unsigned char *input, int ilen,
|
||||
unsigned char output[32], int is224 )
|
||||
{
|
||||
sha2_context ctx;
|
||||
|
||||
sha2_starts( &ctx, is224 );
|
||||
sha2_update( &ctx, input, ilen );
|
||||
sha2_finish( &ctx, output );
|
||||
|
||||
memset( &ctx, 0, sizeof( sha2_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* output = SHA-256( file contents )
|
||||
*/
|
||||
int sha2_file( const char *path, unsigned char output[32], int is224 )
|
||||
{
|
||||
FILE *f;
|
||||
size_t n;
|
||||
sha2_context ctx;
|
||||
unsigned char buf[1024];
|
||||
|
||||
if( ( f = fopen( path, "rb" ) ) == NULL )
|
||||
return( 1 );
|
||||
|
||||
sha2_starts( &ctx, is224 );
|
||||
|
||||
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
|
||||
sha2_update( &ctx, buf, (int) n );
|
||||
|
||||
sha2_finish( &ctx, output );
|
||||
|
||||
memset( &ctx, 0, sizeof( sha2_context ) );
|
||||
|
||||
if( ferror( f ) != 0 )
|
||||
{
|
||||
fclose( f );
|
||||
return( 2 );
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 HMAC context setup
|
||||
*/
|
||||
void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, int keylen,
|
||||
int is224 )
|
||||
{
|
||||
int i;
|
||||
unsigned char sum[32];
|
||||
|
||||
if( keylen > 64 )
|
||||
{
|
||||
sha2( key, keylen, sum, is224 );
|
||||
keylen = ( is224 ) ? 28 : 32;
|
||||
key = sum;
|
||||
}
|
||||
|
||||
memset( ctx->ipad, 0x36, 64 );
|
||||
memset( ctx->opad, 0x5C, 64 );
|
||||
|
||||
for( i = 0; i < keylen; i++ )
|
||||
{
|
||||
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
|
||||
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
|
||||
}
|
||||
|
||||
sha2_starts( ctx, is224 );
|
||||
sha2_update( ctx, ctx->ipad, 64 );
|
||||
|
||||
memset( sum, 0, sizeof( sum ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 HMAC process buffer
|
||||
*/
|
||||
void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, int ilen )
|
||||
{
|
||||
sha2_update( ctx, input, ilen );
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 HMAC final digest
|
||||
*/
|
||||
void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] )
|
||||
{
|
||||
int is224, hlen;
|
||||
unsigned char tmpbuf[32];
|
||||
|
||||
is224 = ctx->is224;
|
||||
hlen = ( is224 == 0 ) ? 32 : 28;
|
||||
|
||||
sha2_finish( ctx, tmpbuf );
|
||||
sha2_starts( ctx, is224 );
|
||||
sha2_update( ctx, ctx->opad, 64 );
|
||||
sha2_update( ctx, tmpbuf, hlen );
|
||||
sha2_finish( ctx, output );
|
||||
|
||||
memset( tmpbuf, 0, sizeof( tmpbuf ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 HMAC context reset
|
||||
*/
|
||||
void sha2_hmac_reset( sha2_context *ctx )
|
||||
{
|
||||
sha2_starts( ctx, ctx->is224 );
|
||||
sha2_update( ctx, ctx->ipad, 64 );
|
||||
}
|
||||
|
||||
/*
|
||||
* output = HMAC-SHA-256( hmac key, input buffer )
|
||||
*/
|
||||
void sha2_hmac( const unsigned char *key, int keylen,
|
||||
const unsigned char *input, int ilen,
|
||||
unsigned char output[32], int is224 )
|
||||
{
|
||||
sha2_context ctx;
|
||||
|
||||
sha2_hmac_starts( &ctx, key, keylen, is224 );
|
||||
sha2_hmac_update( &ctx, input, ilen );
|
||||
sha2_hmac_finish( &ctx, output );
|
||||
|
||||
memset( &ctx, 0, sizeof( sha2_context ) );
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_SELF_TEST)
|
||||
/*
|
||||
* FIPS-180-2 test vectors
|
||||
*/
|
||||
static unsigned char sha2_test_buf[3][57] =
|
||||
{
|
||||
{ "abc" },
|
||||
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
|
||||
{ "" }
|
||||
};
|
||||
|
||||
static const int sha2_test_buflen[3] =
|
||||
{
|
||||
3, 56, 1000
|
||||
};
|
||||
|
||||
static const unsigned char sha2_test_sum[6][32] =
|
||||
{
|
||||
/*
|
||||
* SHA-224 test vectors
|
||||
*/
|
||||
{ 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
|
||||
0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
|
||||
0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
|
||||
0xE3, 0x6C, 0x9D, 0xA7 },
|
||||
{ 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
|
||||
0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
|
||||
0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
|
||||
0x52, 0x52, 0x25, 0x25 },
|
||||
{ 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
|
||||
0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
|
||||
0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
|
||||
0x4E, 0xE7, 0xAD, 0x67 },
|
||||
|
||||
/*
|
||||
* SHA-256 test vectors
|
||||
*/
|
||||
{ 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
|
||||
0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
|
||||
0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
|
||||
0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
|
||||
{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
|
||||
0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
|
||||
0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
|
||||
0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
|
||||
{ 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
|
||||
0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
|
||||
0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
|
||||
0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* RFC 4231 test vectors
|
||||
*/
|
||||
static unsigned char sha2_hmac_test_key[7][26] =
|
||||
{
|
||||
{ "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
|
||||
"\x0B\x0B\x0B\x0B" },
|
||||
{ "Jefe" },
|
||||
{ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
|
||||
"\xAA\xAA\xAA\xAA" },
|
||||
{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
|
||||
"\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
|
||||
{ "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
|
||||
"\x0C\x0C\x0C\x0C" },
|
||||
{ "" }, /* 0xAA 131 times */
|
||||
{ "" }
|
||||
};
|
||||
|
||||
static const int sha2_hmac_test_keylen[7] =
|
||||
{
|
||||
20, 4, 20, 25, 20, 131, 131
|
||||
};
|
||||
|
||||
static unsigned char sha2_hmac_test_buf[7][153] =
|
||||
{
|
||||
{ "Hi There" },
|
||||
{ "what do ya want for nothing?" },
|
||||
{ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
|
||||
{ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
|
||||
{ "Test With Truncation" },
|
||||
{ "Test Using Larger Than Block-Size Key - Hash Key First" },
|
||||
{ "This is a test using a larger than block-size key "
|
||||
"and a larger than block-size data. The key needs to "
|
||||
"be hashed before being used by the HMAC algorithm." }
|
||||
};
|
||||
|
||||
static const int sha2_hmac_test_buflen[7] =
|
||||
{
|
||||
8, 28, 50, 50, 20, 54, 152
|
||||
};
|
||||
|
||||
static const unsigned char sha2_hmac_test_sum[14][32] =
|
||||
{
|
||||
/*
|
||||
* HMAC-SHA-224 test vectors
|
||||
*/
|
||||
{ 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,
|
||||
0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,
|
||||
0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,
|
||||
0x53, 0x68, 0x4B, 0x22 },
|
||||
{ 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,
|
||||
0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,
|
||||
0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,
|
||||
0x8F, 0xD0, 0x5E, 0x44 },
|
||||
{ 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,
|
||||
0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,
|
||||
0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,
|
||||
0xEC, 0x83, 0x33, 0xEA },
|
||||
{ 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,
|
||||
0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,
|
||||
0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,
|
||||
0xE7, 0xAF, 0xEC, 0x5A },
|
||||
{ 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,
|
||||
0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },
|
||||
{ 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,
|
||||
0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,
|
||||
0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,
|
||||
0x3F, 0xA6, 0x87, 0x0E },
|
||||
{ 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,
|
||||
0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,
|
||||
0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,
|
||||
0xF6, 0xF5, 0x65, 0xD1 },
|
||||
|
||||
/*
|
||||
* HMAC-SHA-256 test vectors
|
||||
*/
|
||||
{ 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
|
||||
0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
|
||||
0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
|
||||
0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },
|
||||
{ 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,
|
||||
0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,
|
||||
0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,
|
||||
0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },
|
||||
{ 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,
|
||||
0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,
|
||||
0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,
|
||||
0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },
|
||||
{ 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,
|
||||
0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,
|
||||
0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,
|
||||
0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },
|
||||
{ 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,
|
||||
0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },
|
||||
{ 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,
|
||||
0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,
|
||||
0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,
|
||||
0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },
|
||||
{ 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
|
||||
0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
|
||||
0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
|
||||
0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Checkup routine
|
||||
*/
|
||||
int sha2_self_test( int verbose )
|
||||
{
|
||||
int i, j, k, buflen;
|
||||
unsigned char buf[1024];
|
||||
unsigned char sha2sum[32];
|
||||
sha2_context ctx;
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
j = i % 3;
|
||||
k = i < 3;
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 );
|
||||
|
||||
sha2_starts( &ctx, k );
|
||||
|
||||
if( j == 2 )
|
||||
{
|
||||
memset( buf, 'a', buflen = 1000 );
|
||||
|
||||
for( j = 0; j < 1000; j++ )
|
||||
sha2_update( &ctx, buf, buflen );
|
||||
}
|
||||
else
|
||||
sha2_update( &ctx, sha2_test_buf[j],
|
||||
sha2_test_buflen[j] );
|
||||
|
||||
sha2_finish( &ctx, sha2sum );
|
||||
|
||||
if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "passed\n" );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "\n" );
|
||||
|
||||
for( i = 0; i < 14; i++ )
|
||||
{
|
||||
j = i % 7;
|
||||
k = i < 7;
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
|
||||
|
||||
if( j == 5 || j == 6 )
|
||||
{
|
||||
memset( buf, '\xAA', buflen = 131 );
|
||||
sha2_hmac_starts( &ctx, buf, buflen, k );
|
||||
}
|
||||
else
|
||||
sha2_hmac_starts( &ctx, sha2_hmac_test_key[j],
|
||||
sha2_hmac_test_keylen[j], k );
|
||||
|
||||
sha2_hmac_update( &ctx, sha2_hmac_test_buf[j],
|
||||
sha2_hmac_test_buflen[j] );
|
||||
|
||||
sha2_hmac_finish( &ctx, sha2sum );
|
||||
|
||||
buflen = ( j == 4 ) ? 16 : 32 - k * 4;
|
||||
|
||||
if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "passed\n" );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "\n" );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
155
polarssl/sha2.h
Normal file
155
polarssl/sha2.h
Normal file
@ -0,0 +1,155 @@
|
||||
/**
|
||||
* \file sha2.h
|
||||
*
|
||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef POLARSSL_SHA2_H
|
||||
#define POLARSSL_SHA2_H
|
||||
|
||||
/**
|
||||
* \brief SHA-256 context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned long total[2]; /*!< number of bytes processed */
|
||||
unsigned long state[8]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
|
||||
unsigned char ipad[64]; /*!< HMAC: inner padding */
|
||||
unsigned char opad[64]; /*!< HMAC: outer padding */
|
||||
int is224; /*!< 0 => SHA-256, else SHA-224 */
|
||||
}
|
||||
sha2_context;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief SHA-256 context setup
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
* \param is224 0 = use SHA256, 1 = use SHA224
|
||||
*/
|
||||
void sha2_starts( sha2_context *ctx, int is224 );
|
||||
|
||||
/**
|
||||
* \brief SHA-256 process buffer
|
||||
*
|
||||
* \param ctx SHA-256 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void sha2_update( sha2_context *ctx, const unsigned char *input, int ilen );
|
||||
|
||||
/**
|
||||
* \brief SHA-256 final digest
|
||||
*
|
||||
* \param ctx SHA-256 context
|
||||
* \param output SHA-224/256 checksum result
|
||||
*/
|
||||
void sha2_finish( sha2_context *ctx, unsigned char output[32] );
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-256( input buffer )
|
||||
*
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output SHA-224/256 checksum result
|
||||
* \param is224 0 = use SHA256, 1 = use SHA224
|
||||
*/
|
||||
void sha2( const unsigned char *input, int ilen,
|
||||
unsigned char output[32], int is224 );
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-256( file contents )
|
||||
*
|
||||
* \param path input file name
|
||||
* \param output SHA-224/256 checksum result
|
||||
* \param is224 0 = use SHA256, 1 = use SHA224
|
||||
*
|
||||
* \return 0 if successful, 1 if fopen failed,
|
||||
* or 2 if fread failed
|
||||
*/
|
||||
int sha2_file( const char *path, unsigned char output[32], int is224 );
|
||||
|
||||
/**
|
||||
* \brief SHA-256 HMAC context setup
|
||||
*
|
||||
* \param ctx HMAC context to be initialized
|
||||
* \param key HMAC secret key
|
||||
* \param keylen length of the HMAC key
|
||||
* \param is224 0 = use SHA256, 1 = use SHA224
|
||||
*/
|
||||
void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, int keylen,
|
||||
int is224 );
|
||||
|
||||
/**
|
||||
* \brief SHA-256 HMAC process buffer
|
||||
*
|
||||
* \param ctx HMAC context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, int ilen );
|
||||
|
||||
/**
|
||||
* \brief SHA-256 HMAC final digest
|
||||
*
|
||||
* \param ctx HMAC context
|
||||
* \param output SHA-224/256 HMAC checksum result
|
||||
*/
|
||||
void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] );
|
||||
|
||||
/**
|
||||
* \brief SHA-256 HMAC context reset
|
||||
*
|
||||
* \param ctx HMAC context to be reset
|
||||
*/
|
||||
void sha2_hmac_reset( sha2_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Output = HMAC-SHA-256( hmac key, input buffer )
|
||||
*
|
||||
* \param key HMAC secret key
|
||||
* \param keylen length of the HMAC key
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output HMAC-SHA-224/256 result
|
||||
* \param is224 0 = use SHA256, 1 = use SHA224
|
||||
*/
|
||||
void sha2_hmac( const unsigned char *key, int keylen,
|
||||
const unsigned char *input, int ilen,
|
||||
unsigned char output[32], int is224 );
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int sha2_self_test( int verbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* sha2.h */
|
242
sha1.c
Normal file
242
sha1.c
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 01/08/2005
|
||||
|
||||
This is a byte oriented version of SHA1 that operates on arrays of bytes
|
||||
stored in memory.
|
||||
*/
|
||||
|
||||
#include <string.h> /* for memcpy() etc. */
|
||||
|
||||
#include "sha1.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define SHA1_BLOCK_SIZE 64
|
||||
|
||||
#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
|
||||
#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n)))
|
||||
|
||||
#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00))
|
||||
|
||||
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
|
||||
#define bsw_32(p,n) \
|
||||
{ int _i = (n); while(_i--) ((uint32_t*)p)[_i] = bswap_32(((uint32_t*)p)[_i]); }
|
||||
#else
|
||||
#define bsw_32(p,n)
|
||||
#endif
|
||||
|
||||
#define SHA1_MASK (SHA1_BLOCK_SIZE - 1)
|
||||
|
||||
#if 0
|
||||
|
||||
#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
#define parity(x,y,z) ((x) ^ (y) ^ (z))
|
||||
#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
|
||||
#else /* Discovered by Rich Schroeppel and Colin Plumb */
|
||||
|
||||
#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define parity(x,y,z) ((x) ^ (y) ^ (z))
|
||||
#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y))))
|
||||
|
||||
#endif
|
||||
|
||||
/* Compile 64 bytes of hash data into SHA1 context. Note */
|
||||
/* that this routine assumes that the byte order in the */
|
||||
/* ctx->wbuf[] at this point is in such an order that low */
|
||||
/* address bytes in the ORIGINAL byte stream will go in */
|
||||
/* this buffer to the high end of 32-bit words on BOTH big */
|
||||
/* and little endian systems */
|
||||
|
||||
#ifdef ARRAY
|
||||
#define q(v,n) v[n]
|
||||
#else
|
||||
#define q(v,n) v##n
|
||||
#endif
|
||||
|
||||
#define one_cycle(v,a,b,c,d,e,f,k,h) \
|
||||
q(v,e) += rotr32(q(v,a),27) + \
|
||||
f(q(v,b),q(v,c),q(v,d)) + k + h; \
|
||||
q(v,b) = rotr32(q(v,b), 2)
|
||||
|
||||
#define five_cycle(v,f,k,i) \
|
||||
one_cycle(v, 0,1,2,3,4, f,k,hf(i )); \
|
||||
one_cycle(v, 4,0,1,2,3, f,k,hf(i+1)); \
|
||||
one_cycle(v, 3,4,0,1,2, f,k,hf(i+2)); \
|
||||
one_cycle(v, 2,3,4,0,1, f,k,hf(i+3)); \
|
||||
one_cycle(v, 1,2,3,4,0, f,k,hf(i+4))
|
||||
|
||||
static void sha1_compile(sha1_ctx ctx[1])
|
||||
{ uint32_t *w = ctx->wbuf;
|
||||
|
||||
#ifdef ARRAY
|
||||
uint32_t v[5];
|
||||
memcpy(v, ctx->hash, 5 * sizeof(uint32_t));
|
||||
#else
|
||||
uint32_t v0, v1, v2, v3, v4;
|
||||
v0 = ctx->hash[0]; v1 = ctx->hash[1];
|
||||
v2 = ctx->hash[2]; v3 = ctx->hash[3];
|
||||
v4 = ctx->hash[4];
|
||||
#endif
|
||||
|
||||
#define hf(i) w[i]
|
||||
|
||||
five_cycle(v, ch, 0x5a827999, 0);
|
||||
five_cycle(v, ch, 0x5a827999, 5);
|
||||
five_cycle(v, ch, 0x5a827999, 10);
|
||||
one_cycle(v,0,1,2,3,4, ch, 0x5a827999, hf(15)); \
|
||||
|
||||
#undef hf
|
||||
#define hf(i) (w[(i) & 15] = rotl32( \
|
||||
w[((i) + 13) & 15] ^ w[((i) + 8) & 15] \
|
||||
^ w[((i) + 2) & 15] ^ w[(i) & 15], 1))
|
||||
|
||||
one_cycle(v,4,0,1,2,3, ch, 0x5a827999, hf(16));
|
||||
one_cycle(v,3,4,0,1,2, ch, 0x5a827999, hf(17));
|
||||
one_cycle(v,2,3,4,0,1, ch, 0x5a827999, hf(18));
|
||||
one_cycle(v,1,2,3,4,0, ch, 0x5a827999, hf(19));
|
||||
|
||||
five_cycle(v, parity, 0x6ed9eba1, 20);
|
||||
five_cycle(v, parity, 0x6ed9eba1, 25);
|
||||
five_cycle(v, parity, 0x6ed9eba1, 30);
|
||||
five_cycle(v, parity, 0x6ed9eba1, 35);
|
||||
|
||||
five_cycle(v, maj, 0x8f1bbcdc, 40);
|
||||
five_cycle(v, maj, 0x8f1bbcdc, 45);
|
||||
five_cycle(v, maj, 0x8f1bbcdc, 50);
|
||||
five_cycle(v, maj, 0x8f1bbcdc, 55);
|
||||
|
||||
five_cycle(v, parity, 0xca62c1d6, 60);
|
||||
five_cycle(v, parity, 0xca62c1d6, 65);
|
||||
five_cycle(v, parity, 0xca62c1d6, 70);
|
||||
five_cycle(v, parity, 0xca62c1d6, 75);
|
||||
|
||||
#ifdef ARRAY
|
||||
ctx->hash[0] += v[0]; ctx->hash[1] += v[1];
|
||||
ctx->hash[2] += v[2]; ctx->hash[3] += v[3];
|
||||
ctx->hash[4] += v[4];
|
||||
#else
|
||||
ctx->hash[0] += v0; ctx->hash[1] += v1;
|
||||
ctx->hash[2] += v2; ctx->hash[3] += v3;
|
||||
ctx->hash[4] += v4;
|
||||
#endif
|
||||
}
|
||||
|
||||
void sha1_begin(sha1_ctx ctx[1])
|
||||
{
|
||||
ctx->count[0] = ctx->count[1] = 0;
|
||||
ctx->hash[0] = 0x67452301;
|
||||
ctx->hash[1] = 0xefcdab89;
|
||||
ctx->hash[2] = 0x98badcfe;
|
||||
ctx->hash[3] = 0x10325476;
|
||||
ctx->hash[4] = 0xc3d2e1f0;
|
||||
}
|
||||
|
||||
/* SHA1 hash data in an array of bytes into hash buffer and */
|
||||
/* call the hash_compile function as required. */
|
||||
|
||||
void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1])
|
||||
{ uint32_t pos = (uint32_t)(ctx->count[0] & SHA1_MASK),
|
||||
space = SHA1_BLOCK_SIZE - pos;
|
||||
const unsigned char *sp = data;
|
||||
|
||||
if((ctx->count[0] += len) < len)
|
||||
++(ctx->count[1]);
|
||||
|
||||
while(len >= space) /* tranfer whole blocks if possible */
|
||||
{
|
||||
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);
|
||||
sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0;
|
||||
bsw_32(ctx->wbuf, SHA1_BLOCK_SIZE >> 2);
|
||||
sha1_compile(ctx);
|
||||
}
|
||||
|
||||
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
|
||||
}
|
||||
|
||||
/* SHA1 final padding and digest calculation */
|
||||
|
||||
void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
|
||||
{ uint32_t i = (uint32_t)(ctx->count[0] & SHA1_MASK);
|
||||
|
||||
/* put bytes in the buffer in an order in which references to */
|
||||
/* 32-bit words will put bytes with lower addresses into the */
|
||||
/* top of 32 bit words on BOTH big and little endian machines */
|
||||
bsw_32(ctx->wbuf, (i + 3) >> 2);
|
||||
|
||||
/* we now need to mask valid bytes and add the padding which is */
|
||||
/* a single 1 bit and as many zero bits as necessary. Note that */
|
||||
/* we can always add the first padding byte here because the */
|
||||
/* buffer always has at least one empty slot */
|
||||
ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3);
|
||||
ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3);
|
||||
|
||||
/* we need 9 or more empty positions, one for the padding byte */
|
||||
/* (above) and eight for the length count. If there is not */
|
||||
/* enough space, pad and empty the buffer */
|
||||
if(i > SHA1_BLOCK_SIZE - 9)
|
||||
{
|
||||
if(i < 60) ctx->wbuf[15] = 0;
|
||||
sha1_compile(ctx);
|
||||
i = 0;
|
||||
}
|
||||
else /* compute a word index for the empty buffer positions */
|
||||
i = (i >> 2) + 1;
|
||||
|
||||
while(i < 14) /* and zero pad all but last two positions */
|
||||
ctx->wbuf[i++] = 0;
|
||||
|
||||
/* the following 32-bit length fields are assembled in the */
|
||||
/* wrong byte order on little endian machines but this is */
|
||||
/* corrected later since they are only ever used as 32-bit */
|
||||
/* word values. */
|
||||
ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29);
|
||||
ctx->wbuf[15] = ctx->count[0] << 3;
|
||||
sha1_compile(ctx);
|
||||
|
||||
/* extract the hash value as bytes in case the hash buffer is */
|
||||
/* misaligned for 32-bit words */
|
||||
for(i = 0; i < SHA1_DIGEST_SIZE; ++i)
|
||||
hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3)));
|
||||
}
|
||||
|
||||
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len)
|
||||
{ sha1_ctx cx[1];
|
||||
|
||||
sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx);
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
67
sha1.h
Normal file
67
sha1.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 01/08/2005
|
||||
*/
|
||||
|
||||
#ifndef _SHA1_H
|
||||
#define _SHA1_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#if 0
|
||||
} /* Appleasing Emacs */
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Size of SHA1 digest */
|
||||
|
||||
#define SHA1_DIGEST_SIZE 20
|
||||
|
||||
/* type to hold the SHA1 context */
|
||||
|
||||
typedef struct
|
||||
{ uint32_t count[2];
|
||||
uint32_t hash[5];
|
||||
uint32_t wbuf[16];
|
||||
} sha1_ctx;
|
||||
|
||||
void sha1_begin(sha1_ctx ctx[1]);
|
||||
void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]);
|
||||
void sha1_end(unsigned char hval[], sha1_ctx ctx[1]);
|
||||
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
43
types.h
Normal file
43
types.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef __TYPES_H__
|
||||
#define __TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
typedef signed long long s64;
|
||||
|
||||
typedef enum { false, true } bool;
|
||||
|
||||
enum flags
|
||||
{
|
||||
ExtractFlag = (1<<0),
|
||||
InfoFlag = (1<<1),
|
||||
PlainFlag = (1<<2),
|
||||
VerboseFlag = (1<<3),
|
||||
VerifyFlag = (1<<4),
|
||||
RawFlag = (1<<5),
|
||||
ShowKeysFlag = (1<<6),
|
||||
DecompressCodeFlag = (1<<7)
|
||||
};
|
||||
|
||||
enum validstate
|
||||
{
|
||||
Unchecked = 0,
|
||||
Good = 1,
|
||||
Fail = 2,
|
||||
};
|
||||
|
||||
enum sizeunits
|
||||
{
|
||||
sizeKB = 0x400,
|
||||
sizeMB = 0x100000,
|
||||
};
|
||||
|
||||
#endif
|
252
utils.c
Normal file
252
utils.c
Normal file
@ -0,0 +1,252 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
|
||||
u32 align(u32 offset, u32 alignment)
|
||||
{
|
||||
u32 mask = ~(alignment-1);
|
||||
|
||||
return (offset + (alignment-1)) & mask;
|
||||
}
|
||||
|
||||
u64 align64(u64 offset, u32 alignment)
|
||||
{
|
||||
u64 mask = ~(alignment-1);
|
||||
|
||||
return (offset + (alignment-1)) & mask;
|
||||
}
|
||||
|
||||
u64 getle64(const u8* p)
|
||||
{
|
||||
u64 n = p[0];
|
||||
|
||||
n |= (u64)p[1]<<8;
|
||||
n |= (u64)p[2]<<16;
|
||||
n |= (u64)p[3]<<24;
|
||||
n |= (u64)p[4]<<32;
|
||||
n |= (u64)p[5]<<40;
|
||||
n |= (u64)p[6]<<48;
|
||||
n |= (u64)p[7]<<56;
|
||||
return n;
|
||||
}
|
||||
|
||||
u64 getbe64(const u8* p)
|
||||
{
|
||||
u64 n = 0;
|
||||
|
||||
n |= (u64)p[0]<<56;
|
||||
n |= (u64)p[1]<<48;
|
||||
n |= (u64)p[2]<<40;
|
||||
n |= (u64)p[3]<<32;
|
||||
n |= (u64)p[4]<<24;
|
||||
n |= (u64)p[5]<<16;
|
||||
n |= (u64)p[6]<<8;
|
||||
n |= (u64)p[7]<<0;
|
||||
return n;
|
||||
}
|
||||
|
||||
u32 getle32(const u8* p)
|
||||
{
|
||||
return (p[0]<<0) | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
|
||||
}
|
||||
|
||||
u32 getbe32(const u8* p)
|
||||
{
|
||||
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | (p[3]<<0);
|
||||
}
|
||||
|
||||
u32 getle16(const u8* p)
|
||||
{
|
||||
return (p[0]<<0) | (p[1]<<8);
|
||||
}
|
||||
|
||||
u32 getbe16(const u8* p)
|
||||
{
|
||||
return (p[0]<<8) | (p[1]<<0);
|
||||
}
|
||||
|
||||
void putle16(u8* p, u16 n)
|
||||
{
|
||||
p[0] = n;
|
||||
p[1] = n>>8;
|
||||
}
|
||||
|
||||
void putle32(u8* p, u32 n)
|
||||
{
|
||||
p[0] = n;
|
||||
p[1] = n>>8;
|
||||
p[2] = n>>16;
|
||||
p[3] = n>>24;
|
||||
}
|
||||
|
||||
|
||||
void readkeyfile(u8* key, const char* keyfname)
|
||||
{
|
||||
FILE* f = fopen(keyfname, "rb");
|
||||
u32 keysize = 0;
|
||||
|
||||
if (0 == f)
|
||||
{
|
||||
fprintf(stdout, "Error opening key file\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
keysize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
if (keysize != 16)
|
||||
{
|
||||
fprintf(stdout, "Error key size mismatch, got %d, expected %d\n", keysize, 16);
|
||||
goto clean;
|
||||
}
|
||||
|
||||
if (16 != fread(key, 1, 16, f))
|
||||
{
|
||||
fprintf(stdout, "Error reading key file\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
clean:
|
||||
if (f)
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void hexdump(void *ptr, int buflen)
|
||||
{
|
||||
u8 *buf = (u8*)ptr;
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<buflen; i+=16)
|
||||
{
|
||||
printf("%06x: ", i);
|
||||
for (j=0; j<16; j++)
|
||||
{
|
||||
if (i+j < buflen)
|
||||
{
|
||||
printf("%02x ", buf[i+j]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
|
||||
for (j=0; j<16; j++)
|
||||
{
|
||||
if (i+j < buflen)
|
||||
{
|
||||
printf("%c", (buf[i+j] >= 0x20 && buf[i+j] <= 0x7e) ? buf[i+j] : '.');
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void memdump(FILE* fout, const char* prefix, const u8* data, u32 size)
|
||||
{
|
||||
u32 i;
|
||||
u32 prefixlen = strlen(prefix);
|
||||
u32 offs = 0;
|
||||
u32 line = 0;
|
||||
while(size)
|
||||
{
|
||||
u32 max = 32;
|
||||
|
||||
if (max > size)
|
||||
max = size;
|
||||
|
||||
if (line==0)
|
||||
fprintf(fout, "%s", prefix);
|
||||
else
|
||||
fprintf(fout, "%*s", prefixlen, "");
|
||||
|
||||
|
||||
for(i=0; i<max; i++)
|
||||
fprintf(fout, "%02X", data[offs+i]);
|
||||
fprintf(fout, "\n");
|
||||
line++;
|
||||
size -= max;
|
||||
offs += max;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ishex(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return 1;
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return 1;
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static unsigned char hextobin(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c-'0';
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return c-'A'+0xA;
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return c-'a'+0xA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hex2bytes(const char* text, unsigned int textlen, unsigned char* bytes, unsigned int size)
|
||||
{
|
||||
unsigned int i, j;
|
||||
unsigned int hexcount = 0;
|
||||
|
||||
for(i=0; i<textlen; i++)
|
||||
{
|
||||
if (ishex(text[i]))
|
||||
hexcount++;
|
||||
}
|
||||
|
||||
if (hexcount != size*2)
|
||||
{
|
||||
fprintf(stdout, "Error, expected %d hex characters when parsing text \"", size*2);
|
||||
for(i=0; i<textlen; i++)
|
||||
fprintf(stdout, "%c", text[i]);
|
||||
fprintf(stdout, "\"\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i=0, j=0; i<textlen; i++)
|
||||
{
|
||||
if (ishex(text[i]))
|
||||
{
|
||||
if ( (j&1) == 0 )
|
||||
bytes[j/2] = hextobin(text[i])<<4;
|
||||
else
|
||||
bytes[j/2] |= hextobin(text[i]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int makedir(const char* dir)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _mkdir(dir);
|
||||
#else
|
||||
return mkdir(dir, 0777);
|
||||
#endif
|
||||
}
|
43
utils.h
Normal file
43
utils.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PATH_SEPERATOR '\\'
|
||||
#else
|
||||
#define PATH_SEPERATOR '/'
|
||||
#endif
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 255
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
u32 align(u32 offset, u32 alignment);
|
||||
u64 align64(u64 offset, u32 alignment);
|
||||
u64 getle64(const u8* p);
|
||||
u32 getle32(const u8* p);
|
||||
u32 getle16(const u8* p);
|
||||
u64 getbe64(const u8* p);
|
||||
u32 getbe32(const u8* p);
|
||||
u32 getbe16(const u8* p);
|
||||
void putle16(u8* p, u16 n);
|
||||
void putle32(u8* p, u32 n);
|
||||
|
||||
void readkeyfile(u8* key, const char* keyfname);
|
||||
void memdump(FILE* fout, const char* prefix, const u8* data, u32 size);
|
||||
void hexdump(void *ptr, int buflen);
|
||||
int key_load(char *name, u8 *out_buf);
|
||||
int hex2bytes(const char* text, unsigned int textlen, unsigned char* bytes, unsigned int size);
|
||||
|
||||
int makedir(const char* dir);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _UTILS_H_
|
Loading…
Reference in New Issue
Block a user