4b475a4fcbe807d0e0d0894027873764861dba12
[pam_pcsc_cr.git] / ossl_crypto.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <openssl/err.h>
5 #include <openssl/sha.h>
6 #include <openssl/evp.h>
7 #include <openssl/hmac.h>
8
9 #include "crypto_if.h"
10
11 static const char *ossl_init(void)
12 {
13         ERR_load_crypto_strings();
14         return "openssl";
15 }
16
17 static unsigned long ossl_encrypt(void *key, int keylen, void *iv,
18                         void *pt, void *ct, int tlen)
19 {
20         EVP_CIPHER_CTX ctx;
21         int outlen1, outlen2;
22         unsigned char hkey[16];
23
24         if (EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(),
25                         NULL, key, keylen, 5, hkey, NULL) != 16) return 1UL;
26         if (!EVP_EncryptInit(&ctx, EVP_aes_128_cbc(), hkey, iv))
27                 return ERR_get_error();
28         if (!EVP_EncryptUpdate(&ctx, ct, &outlen1, pt, tlen))
29                 return ERR_get_error();
30         if (!EVP_EncryptFinal(&ctx, ct + outlen1, &outlen2))
31                 return ERR_get_error();
32         if (outlen1 + outlen2 != tlen) {
33                 printf("enc tlen =%d outlen1=%d outlen2=%d\n",
34                         tlen, outlen1, outlen2);
35                 // return 1UL;
36         }
37         return 0UL;
38 }
39
40 static unsigned long ossl_decrypt(void *key, int keylen, void *iv,
41                         void *ct, void *pt, int tlen)
42 {
43         EVP_CIPHER_CTX ctx;
44         int outlen1, outlen2;
45         unsigned char hkey[16];
46
47         if (EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(),
48                         NULL, key, keylen, 5, hkey, NULL) != 16) return 1UL;
49         if (!EVP_DecryptInit(&ctx, EVP_aes_128_cbc(), hkey, iv))
50                 return ERR_get_error();
51         if (!EVP_DecryptUpdate(&ctx, ct, &outlen1, pt, tlen))
52                 return ERR_get_error();
53         if (!EVP_DecryptFinal(&ctx, ct + outlen1, &outlen2))
54                 return ERR_get_error();
55         if (outlen1 + outlen2 != tlen) {
56                 printf("dec tlen =%d outlen1=%d outlen2=%d\n",
57                         tlen, outlen1, outlen2);
58                 // return 1UL;
59         }
60         return 0UL;
61 }
62
63 static unsigned long ossl_hash(void *pt, int tlen, void *tag, int *taglen)
64 {
65         SHA_CTX sctx;
66
67         if (!SHA1_Init(&sctx)) return ERR_get_error();
68         if (!SHA1_Update(&sctx, pt, tlen)) return ERR_get_error();
69         if (!SHA1_Final(tag, &sctx)) return ERR_get_error();
70         *taglen = 20;
71         return 0UL;
72 }
73
74 static unsigned long ossl_hmac(void *pt, int tlen, void *key, int keylen,
75                         void *tag, int *taglen)
76 {
77         if (!HMAC(EVP_sha1(), key, keylen, pt, tlen,
78                                 tag, (unsigned int *)taglen))
79                         return ERR_get_error();
80         return 0UL;
81 }
82
83 static const char *ossl_errstr(unsigned long err)
84 {
85         return ERR_error_string(err, NULL);
86 }
87
88 struct crypto_interface ossl_crypto_if = {
89         .init           = ossl_init,
90         .encrypt        = ossl_encrypt,
91         .decrypt        = ossl_decrypt,
92         .hash           = ossl_hash,
93         .hmac           = ossl_hmac,
94         .errstr         = ossl_errstr,
95 };