summaryrefslogtreecommitdiff
path: root/src/crypto-tomcrypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto-tomcrypt.c')
-rw-r--r--src/crypto-tomcrypt.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/crypto-tomcrypt.c b/src/crypto-tomcrypt.c
new file mode 100644
index 0000000..b19c724
--- /dev/null
+++ b/src/crypto-tomcrypt.c
@@ -0,0 +1,211 @@
+/*
+ * crypto-tomgrypt.c - Cryptography routines needed by mrtreader using
+ * libtomcrypt.
+ *
+ * Copyright (C) 2014 Ruben Undheim <ruben.undheim@gmail.com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <tomcrypt.h>
+
+
+void mrtd_crypto_sha1(const uint8_t *input, const int length, uint8_t *output)
+{
+ hash_state md;
+ sha1_init(&md);
+ sha1_process(&md, (const unsigned char*) input, length);
+ sha1_done(&md, output);
+}
+
+void mrtd_crypto_crypt_des(const uint8_t *input, uint8_t *output, const int length, const uint8_t *key, const char encrypt)
+{
+ int err;
+ symmetric_CBC cbc_state;
+ char IV[8];
+
+ memset(IV,0,8);
+
+ if(register_cipher(&des_desc) == -1){
+ printf("Error registering cipher\n");
+ }
+ if((err = cbc_start(find_cipher("des"),IV,key,8,0,&cbc_state)) != CRYPT_OK){
+ printf("cbc_start error: %s\n", error_to_string(err));
+ }
+ if(encrypt){
+ if((err = cbc_encrypt(input,output,length,&cbc_state)) != CRYPT_OK){
+ printf("cbc_encrypt error: %s\n", error_to_string(err));
+ }
+ }
+ else{
+ if((err = cbc_decrypt(input,output,length,&cbc_state)) != CRYPT_OK){
+ printf("cbc_encrypt error: %s\n", error_to_string(err));
+ }
+ }
+ if((err = cbc_done(&cbc_state)) != CRYPT_OK){
+ printf("cbc_done error: %s\n", error_to_string(err));
+ }
+}
+
+void mrtd_crypto_encrypt_des(const uint8_t *input, uint8_t *output, const int length, const uint8_t *key)
+{
+ mrtd_crypto_crypt_des(input,output,length,key,1);
+}
+
+void mrtd_crypto_decrypt_des(const uint8_t *input, uint8_t *output, const int length, const uint8_t *key)
+{
+ mrtd_crypto_crypt_des(input,output,length,key,0);
+}
+
+void mrtd_crypto_crypt_3des(const uint8_t *input, uint8_t *output, const int length, const uint8_t *key, const char encrypt)
+{
+ int err;
+ symmetric_CBC cbc_state;
+ char longkey[24];
+ char IV[8];
+
+ memcpy(longkey,key,16);
+ memcpy(longkey+16,key,8);
+ memset(IV,0,8);
+
+ if(register_cipher(&des3_desc) == -1){
+ printf("Error registering cipher\n");
+ exit(-1);
+ }
+ if((err = cbc_start(find_cipher("3des"),IV,longkey,24,0,&cbc_state)) != CRYPT_OK){
+ printf("cbc_start error: %s\n", error_to_string(err));
+ exit(-1);
+ }
+ if(encrypt){
+ if((err = cbc_encrypt(input,output,length,&cbc_state)) != CRYPT_OK){
+ printf("cbc_encrypt error: %s\n", error_to_string(err));
+ exit(-1);
+ }
+ }
+ else{
+ if((err = cbc_decrypt(input,output,length,&cbc_state)) != CRYPT_OK){
+ printf("cbc_encrypt error: %s\n", error_to_string(err));
+ exit(-1);
+ }
+ }
+}
+
+void mrtd_crypto_encrypt_3des(const uint8_t *input, uint8_t *output, const int length, const uint8_t *key)
+{
+ mrtd_crypto_crypt_3des(input,output,length,key,1);
+}
+
+void mrtd_crypto_decrypt_3des(const uint8_t *input, uint8_t *output, const int length, const uint8_t *key)
+{
+ mrtd_crypto_crypt_3des(input,output,length,key,0);
+}
+
+void mrtd_crypto_fix_parity(const uint8_t *input, uint8_t *output, const int length, int *newlength)
+{
+ int i,j;
+ unsigned char y;
+ int parity;
+ *newlength = length+(length/8);
+ for(i=0;i<length;i++){
+ y = input[i] & 0xfe;
+ parity = 0;
+ for(j=0;j<8;j++){
+ parity += y >> j & 1;
+ }
+ if(parity % 2 == 0){
+ output[i] = (char)(y + 1);
+ }
+ else{
+ output[i] = y;
+ }
+ }
+
+}
+void mrtd_crypto_padding(const uint8_t *input, uint8_t *output, const int length, int *newlength)
+{
+ *newlength = ((length+8)/8)*8;
+ memset(output,0,*newlength);
+ memcpy(output,input,length);
+ output[length] = 0x80;
+}
+void mrtd_crypto_padding_remove(const uint8_t *input, uint8_t *output, const int length, int *newlength)
+{
+ int i;
+ int pos;
+ char found = 0;
+ for(i=length-1;i>=0;i--){
+ if(input[i] == 0x00) {
+ continue;
+ }
+ else if(input[i] == 0x80) {
+ pos = i;
+ found = 1;
+ break;
+ }
+ else {
+ goto failed;
+ }
+ }
+ if(found){
+ *newlength = pos;
+ memcpy(output,input,*newlength);
+ }
+ else{
+ goto failed;
+ }
+
+ return;
+
+ failed:
+ *newlength = 0;
+ return;
+}
+
+void mrtd_crypto_mac(const uint8_t *input, uint8_t *output, const int length, const uint8_t *key)
+{
+ int i,j;
+ uint8_t current[8];
+ uint8_t mac[8];
+ uint8_t xormac[8];
+ uint8_t tmp[8];
+ memset(mac,0,8);
+ for(i=0;i<(length/8);i++){
+ for(j=0;j<8;j++){
+ current[j] = input[i*8+j];
+ }
+ for(j=0;j<8;j++){
+ xormac[j] = mac[j] ^ current[j];
+ }
+ mrtd_crypto_encrypt_des(xormac,mac,8,key);
+ }
+ mrtd_crypto_decrypt_des(mac,tmp,8,key+8);
+ mrtd_crypto_encrypt_des(tmp,output,8,key);
+}
+
+void mrtd_crypto_mac_padding(const uint8_t *input, uint8_t *output, const int length, const uint8_t *key)
+{
+ int newlength;
+ uint8_t *tmp;
+ tmp = malloc(((length+8)/8)*8);
+ mrtd_crypto_padding(input,tmp,length,&newlength);
+ mrtd_crypto_mac(tmp,output,newlength,key);
+
+ free(tmp);
+}