1 /* Written by Ben Laurie, 2001 */
3 * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
17 * 3. All advertising materials mentioning features or use of this
18 * software must display the following acknowledgment:
19 * "This product includes software developed by the OpenSSL Project
20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 * endorse or promote products derived from this software without
24 * prior written permission. For written permission, please contact
25 * openssl-core@openssl.org.
27 * 5. Products derived from this software may not be called "OpenSSL"
28 * nor may "OpenSSL" appear in their names without prior written
29 * permission of the OpenSSL Project.
31 * 6. Redistributions of any form whatsoever must retain the following
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 #include <openssl/evp.h>
51 #include <openssl/objects.h>
52 #include <openssl/rsa.h>
56 * This stuff should now all be supported through
57 * crypto/engine/hw_openbsd_dev_crypto.c unless I botched it up
59 static void *dummy
= &dummy
;
63 /* check flag after OpenSSL headers to ensure make depend works */
64 # ifdef OPENSSL_OPENBSD_DEV_CRYPTO
69 # include <sys/ioctl.h>
70 # include <crypto/cryptodev.h>
74 /* longest key supported in hardware */
75 # define MAX_HW_KEY 24
78 # define MD5_DIGEST_LENGTH 16
79 # define MD5_CBLOCK 64
82 static int dev_failed
;
84 typedef struct session_op session_op
;
86 # define CDATA(ctx) EVP_C_DATA(session_op,ctx)
88 static void err(const char *str
)
90 fprintf(stderr
, "%s: errno %d\n", str
, errno
);
93 static int dev_crypto_init(session_op
*ses
)
100 if ((cryptodev_fd
= open("/dev/crypto", O_RDWR
, 0)) < 0) {
105 if (ioctl(cryptodev_fd
, CRIOGET
, &fd
) == -1) {
106 err("CRIOGET failed");
114 memset(ses
, '\0', sizeof *ses
);
119 static int dev_crypto_cleanup(EVP_CIPHER_CTX
*ctx
)
121 if (ioctl(fd
, CIOCFSESSION
, &CDATA(ctx
)->ses
) == -1)
122 err("CIOCFSESSION failed");
124 OPENSSL_free(CDATA(ctx
)->key
);
129 static int dev_crypto_init_key(EVP_CIPHER_CTX
*ctx
, int cipher
,
130 const unsigned char *key
, int klen
)
132 if (!dev_crypto_init(CDATA(ctx
)))
135 CDATA(ctx
)->key
= OPENSSL_malloc(MAX_HW_KEY
);
137 assert(ctx
->cipher
->iv_len
<= MAX_HW_IV
);
139 memcpy(CDATA(ctx
)->key
, key
, klen
);
141 CDATA(ctx
)->cipher
= cipher
;
142 CDATA(ctx
)->keylen
= klen
;
144 if (ioctl(fd
, CIOCGSESSION
, CDATA(ctx
)) == -1) {
145 err("CIOCGSESSION failed");
151 static int dev_crypto_cipher(EVP_CIPHER_CTX
*ctx
, unsigned char *out
,
152 const unsigned char *in
, unsigned int inl
)
154 struct crypt_op cryp
;
155 unsigned char lb
[MAX_HW_IV
];
163 memset(&cryp
, '\0', sizeof cryp
);
164 cryp
.ses
= CDATA(ctx
)->ses
;
165 cryp
.op
= ctx
->encrypt
? COP_ENCRYPT
: COP_DECRYPT
;
168 assert((inl
& (ctx
->cipher
->block_size
- 1)) == 0);
169 cryp
.src
= (caddr_t
) in
;
170 cryp
.dst
= (caddr_t
) out
;
172 if (ctx
->cipher
->iv_len
)
173 cryp
.iv
= (caddr_t
) ctx
->iv
;
176 memcpy(lb
, &in
[cryp
.len
- ctx
->cipher
->iv_len
], ctx
->cipher
->iv_len
);
178 if (ioctl(fd
, CIOCCRYPT
, &cryp
) == -1) {
179 if (errno
== EINVAL
) { /* buffers are misaligned */
180 unsigned int cinl
= 0;
184 /* NB: this can only make cinl != inl with stream ciphers */
185 cinl
= (inl
+ 3) / 4 * 4;
187 if (((unsigned long)in
& 3) || cinl
!= inl
) {
188 cin
= OPENSSL_malloc(cinl
);
189 memcpy(cin
, in
, inl
);
193 if (((unsigned long)out
& 3) || cinl
!= inl
) {
194 cout
= OPENSSL_malloc(cinl
);
200 if (ioctl(fd
, CIOCCRYPT
, &cryp
) == -1) {
201 err("CIOCCRYPT(2) failed");
202 printf("src=%p dst=%p\n", cryp
.src
, cryp
.dst
);
208 memcpy(out
, cout
, inl
);
214 err("CIOCCRYPT failed");
221 memcpy(ctx
->iv
, &out
[cryp
.len
- ctx
->cipher
->iv_len
],
222 ctx
->cipher
->iv_len
);
224 memcpy(ctx
->iv
, lb
, ctx
->cipher
->iv_len
);
229 static int dev_crypto_des_ede3_init_key(EVP_CIPHER_CTX
*ctx
,
230 const unsigned char *key
,
231 const unsigned char *iv
, int enc
)
233 return dev_crypto_init_key(ctx
, CRYPTO_3DES_CBC
, key
, 24);
236 # define dev_crypto_des_ede3_cbc_cipher dev_crypto_cipher
238 BLOCK_CIPHER_def_cbc(dev_crypto_des_ede3
, session_op
, NID_des_ede3
, 8, 24, 8,
239 0, dev_crypto_des_ede3_init_key
,
241 EVP_CIPHER_set_asn1_iv
, EVP_CIPHER_get_asn1_iv
, NULL
)
243 static int dev_crypto_rc4_init_key(EVP_CIPHER_CTX
*ctx
,
244 const unsigned char *key
,
245 const unsigned char *iv
, int enc
)
247 return dev_crypto_init_key(ctx
, CRYPTO_ARC4
, key
, 16);
250 static const EVP_CIPHER r4_cipher
= {
252 1, 16, 0, /* FIXME: key should be up to 256 bytes */
253 EVP_CIPH_VARIABLE_LENGTH
,
254 dev_crypto_rc4_init_key
,
263 const EVP_CIPHER
*EVP_dev_crypto_rc4(void)
272 unsigned char md
[EVP_MAX_MD_SIZE
];
275 static int dev_crypto_init_digest(MD_DATA
*md_data
, int mac
)
277 if (!dev_crypto_init(&md_data
->sess
))
281 md_data
->data
= NULL
;
283 md_data
->sess
.mac
= mac
;
285 if (ioctl(fd
, CIOCGSESSION
, &md_data
->sess
) == -1) {
286 err("CIOCGSESSION failed");
292 static int dev_crypto_cleanup_digest(MD_DATA
*md_data
)
294 if (ioctl(fd
, CIOCFSESSION
, &md_data
->sess
.ses
) == -1) {
295 err("CIOCFSESSION failed");
302 /* FIXME: if device can do chained MACs, then don't accumulate */
303 /* FIXME: move accumulation to the framework */
304 static int dev_crypto_md5_init(EVP_MD_CTX
*ctx
)
306 return dev_crypto_init_digest(ctx
->md_data
, CRYPTO_MD5
);
309 static int do_digest(int ses
, unsigned char *md
, const void *data
, int len
)
311 struct crypt_op cryp
;
312 static unsigned char md5zero
[16] = {
313 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
314 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
317 /* some cards can't do zero length */
319 memcpy(md
, md5zero
, 16);
323 memset(&cryp
, '\0', sizeof cryp
);
325 cryp
.op
= COP_ENCRYPT
; /* required to do the MAC rather than check
328 cryp
.src
= (caddr_t
) data
;
329 cryp
.dst
= (caddr_t
) data
; // FIXME!!!
330 cryp
.mac
= (caddr_t
) md
;
332 if (ioctl(fd
, CIOCCRYPT
, &cryp
) == -1) {
333 if (errno
== EINVAL
) { /* buffer is misaligned */
336 dcopy
= OPENSSL_malloc(len
);
337 memcpy(dcopy
, data
, len
);
339 cryp
.dst
= cryp
.src
; // FIXME!!!
341 if (ioctl(fd
, CIOCCRYPT
, &cryp
) == -1) {
342 err("CIOCCRYPT(MAC2) failed");
348 err("CIOCCRYPT(MAC) failed");
358 static int dev_crypto_md5_update(EVP_MD_CTX
*ctx
, const void *data
,
361 MD_DATA
*md_data
= ctx
->md_data
;
363 if (ctx
->flags
& EVP_MD_CTX_FLAG_ONESHOT
)
364 return do_digest(md_data
->sess
.ses
, md_data
->md
, data
, len
);
366 md_data
->data
= OPENSSL_realloc(md_data
->data
, md_data
->len
+ len
);
367 memcpy(md_data
->data
+ md_data
->len
, data
, len
);
373 static int dev_crypto_md5_final(EVP_MD_CTX
*ctx
, unsigned char *md
)
376 MD_DATA
*md_data
= ctx
->md_data
;
378 if (ctx
->flags
& EVP_MD_CTX_FLAG_ONESHOT
) {
379 memcpy(md
, md_data
->md
, MD5_DIGEST_LENGTH
);
382 ret
= do_digest(md_data
->sess
.ses
, md
, md_data
->data
, md_data
->len
);
383 OPENSSL_free(md_data
->data
);
384 md_data
->data
= NULL
;
391 static int dev_crypto_md5_copy(EVP_MD_CTX
*to
, const EVP_MD_CTX
*from
)
393 const MD_DATA
*from_md
= from
->md_data
;
394 MD_DATA
*to_md
= to
->md_data
;
396 // How do we copy sessions?
397 assert(from
->digest
->flags
& EVP_MD_FLAG_ONESHOT
);
399 to_md
->data
= OPENSSL_malloc(from_md
->len
);
400 memcpy(to_md
->data
, from_md
->data
, from_md
->len
);
405 static int dev_crypto_md5_cleanup(EVP_MD_CTX
*ctx
)
407 return dev_crypto_cleanup_digest(ctx
->md_data
);
410 static const EVP_MD md5_md
= {
412 NID_md5WithRSAEncryption
,
414 EVP_MD_FLAG_ONESHOT
, // XXX: set according to device info...
416 dev_crypto_md5_update
,
417 dev_crypto_md5_final
,
419 dev_crypto_md5_cleanup
,
425 const EVP_MD
*EVP_dev_crypto_md5(void)