1/*
2 * Copyright (c) 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34/* Windows crypto provider plugin, sample */
35
36#include <config.h>
37
38#define HC_DEPRECATED
39
40#include <sys/types.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <assert.h>
45
46#include <evp.h>
47
48#include <crypt.h>
49
50
51static HCRYPTPROV hCryptProv = NULL;
52
53/*
54 *
55 */
56
57struct generic_key {
58    HCRYPTKEY *hKey;
59};
60
61static int
62generic_cbc_do_cipher(EVP_CIPHER_CTX *ctx,
63		       unsigned char *out,
64		       const unsigned char *in,
65		       unsigned int size)
66{
67    struct generic_key *gk = ctx->cipher_data;
68    BOOL bResult;
69    DWORD length = size;
70
71    bResult = CryptSetKeyParam(gk->hKey, KP_IV, ctx->iv, 0);
72    _ASSERT(bResult);
73
74    memcpy(out, in, size);
75
76    if (ctx->encrypt)
77	bResult = CryptEncrypt(gk->hKey, 0, TRUE, 0, out, &length, size);
78    else
79	bResult = CryptDecrypt(gk->hKey, 0, TRUE, 0, out, &length);
80    _ASSERT(bResult);
81
82    return 1;
83}
84
85static int
86generic_cleanup(EVP_CIPHER_CTX *ctx)
87{
88    struct generic_key *gk = ctx->cipher_data;
89    CryptDestroyKey(gk->hKey);
90    gk->hKey = NULL;
91    return 1;
92}
93
94static HCRYPTKEY
95import_key(int alg, const unsigned char *key, size_t keylen)
96{
97    struct {
98	BLOBHEADER hdr;
99	DWORD len;
100	BYTE key[1];
101    } *key_blob;
102    size_t bloblen = sizeof(*key_blob) - 1 + keylen;
103
104    key_blob = malloc(bloblen);
105
106    key_blob->hdr.bType = PLAINTEXTKEYBLOB;
107    key_blob->hdr.bVersion = CUR_BLOB_VERSION;
108    key_blob->hdr.reserved = 0;
109    key_blob->hdr.aiKeyAlg = alg;
110    key_blob->len = 24;
111    memcpy(key_blob->key, key, keylen);
112
113    bResult = CryptImportKey(hCryptProv,
114			     (void *)key_blob, bloblen, 0, 0,
115			     &gk->hKey);
116    free(key_blob);
117    _ASSERT(bResult);
118
119    return hKey;
120}
121
122static int
123crypto_des_ede3_cbc_init(EVP_CIPHER_CTX *ctx,
124			 const unsigned char * key,
125			 const unsigned char * iv,
126			 int encp)
127{
128    struct generic_key *gk = ctx->cipher_data;
129    DWORD paramData;
130
131    gk->hKey = import_key(CALG_3DES,
132			  key->key->keyvalue.data,
133			  key->key->keyvalue.len);
134
135    return 1;
136}
137
138/**
139 * The tripple DES cipher type (Micrsoft crypt provider)
140 *
141 * @return the DES-EDE3-CBC EVP_CIPHER pointer.
142 *
143 * @ingroup hcrypto_evp
144 */
145
146const EVP_CIPHER *
147EVP_wincrypt_des_ede3_cbc(void)
148{
149    static const EVP_CIPHER des_ede3_cbc = {
150	0,
151	8,
152	24,
153	8,
154	EVP_CIPH_CBC_MODE,
155	crypto_des_ede3_cbc_init,
156	generic_cbc_do_cipher,
157	generic_cleanup,
158	sizeof(struct generic_key),
159	NULL,
160	NULL,
161	NULL,
162	NULL
163    };
164    return &des_ede3_cbc;
165}
166
167/*
168 *
169 */
170
171struct generic_hash {
172    HCRYPTHASH hHash;
173};
174
175static void
176crypto_md5_init(struct generic_hash *m);
177{
178    BOOL bResult;
179    bResult = CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &m->hHash);
180    _ASSERT(bResult);
181}
182
183static void
184generic_hash_update (struct generic_hash *m, const void *p, size_t len)
185{
186    BOOL bResult;
187    bResult = CryptHashData(m->hHash, data, ( DWORD )len, 0 );
188    _ASSERT(bResult);
189}
190
191static void
192generic_hash_final (void *res, struct generic_hash *m);
193{
194    DWORD length;
195    BOOL bResult;
196    bResult = CryptGetHashParam(m->hHash, HP_HASHVAL, res, &length, 0)
197    _ASSERT(bResult);
198}
199
200static void
201generic_hash_cleanup(struct generic_hash *m)
202{
203    CryptDestroyHash(m->hHash);
204    m->hHash = NULL;
205}
206
207const EVP_MD *
208EVP_wincrypt_md5(void)
209{
210    static const struct hc_evp_md md5 = {
211	16,
212	64,
213	sizeof(struct generic_hash),
214	(hc_evp_md_init)crypto_md5_init,
215	(hc_evp_md_update)generic_hash_update,
216	(hc_evp_md_final)generic_hash_final,
217	(hc_evp_md_cleanup)generic_hash_cleanup
218    };
219    return &md5;
220}
221