Deleted Added
full compact
2,3c2
< * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
< * Copyright (c) 2004 Mark R V Murray
---
> * Copyright (c) 2005-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
28,46d26
< /* $OpenBSD: via.c,v 1.3 2004/06/15 23:36:55 deraadt Exp $ */
< /*-
< * Copyright (c) 2003 Jason Wright
< * Copyright (c) 2003, 2004 Theo de Raadt
< * All rights reserved.
< *
< * Permission to use, copy, modify, and distribute this software for any
< * purpose with or without fee is hereby granted, provided that the above
< * copyright notice and this permission notice appear in all copies.
< *
< * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
< * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
< * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
< * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
< * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
< * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
< * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
< */
<
48c28
< __FBSDID("$FreeBSD: head/sys/crypto/via/padlock.c 160573 2006-07-22 13:14:11Z pjd $");
---
> __FBSDID("$FreeBSD: head/sys/crypto/via/padlock.c 160582 2006-07-22 16:18:47Z pjd $");
66,68d45
< #include <opencrypto/cryptosoft.h> /* for hmac_ipad_buffer and hmac_opad_buffer */
< #include <opencrypto/xform.h>
< #include <crypto/rijndael/rijndael.h>
69a47
> #include <crypto/via/padlock.h>
71,73c49,53
< #define PADLOCK_ROUND_COUNT_AES128 10
< #define PADLOCK_ROUND_COUNT_AES192 12
< #define PADLOCK_ROUND_COUNT_AES256 14
---
> /*
> * Technical documentation about the PadLock engine can be found here:
> *
> * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/programming_guide.pdf
> */
75,126d54
< #define PADLOCK_ALGORITHM_TYPE_AES 0
<
< #define PADLOCK_KEY_GENERATION_HW 0
< #define PADLOCK_KEY_GENERATION_SW 1
<
< #define PADLOCK_DIRECTION_ENCRYPT 0
< #define PADLOCK_DIRECTION_DECRYPT 1
<
< #define PADLOCK_KEY_SIZE_128 0
< #define PADLOCK_KEY_SIZE_192 1
< #define PADLOCK_KEY_SIZE_256 2
<
< union padlock_cw {
< uint64_t raw;
< struct {
< u_int round_count : 4;
< u_int algorithm_type : 3;
< u_int key_generation : 1;
< u_int intermediate : 1;
< u_int direction : 1;
< u_int key_size : 2;
< u_int filler0 : 20;
< u_int filler1 : 32;
< u_int filler2 : 32;
< u_int filler3 : 32;
< } __field;
< };
< #define cw_round_count __field.round_count
< #define cw_algorithm_type __field.algorithm_type
< #define cw_key_generation __field.key_generation
< #define cw_intermediate __field.intermediate
< #define cw_direction __field.direction
< #define cw_key_size __field.key_size
< #define cw_filler0 __field.filler0
< #define cw_filler1 __field.filler1
< #define cw_filler2 __field.filler2
< #define cw_filler3 __field.filler3
<
< struct padlock_session {
< union padlock_cw ses_cw __aligned(16);
< uint32_t ses_ekey[4 * (RIJNDAEL_MAXNR + 1) + 4] __aligned(16); /* 128 bit aligned */
< uint32_t ses_dkey[4 * (RIJNDAEL_MAXNR + 1) + 4] __aligned(16); /* 128 bit aligned */
< uint8_t ses_iv[16] __aligned(16); /* 128 bit aligned */
< struct auth_hash *ses_axf;
< uint8_t *ses_ictx;
< uint8_t *ses_octx;
< int ses_mlen;
< int ses_used;
< uint32_t ses_id;
< TAILQ_ENTRY(padlock_session) ses_next;
< };
<
142,158c70
< static __inline void
< padlock_cbc(void *in, void *out, size_t count, void *key, union padlock_cw *cw,
< void *iv)
< {
< #ifdef __GNUCLIKE_ASM
< /* The .byte line is really VIA C3 "xcrypt-cbc" instruction */
< __asm __volatile(
< "pushf \n\t"
< "popf \n\t"
< "rep \n\t"
< ".byte 0x0f, 0xa7, 0xd0"
< : "+a" (iv), "+c" (count), "+D" (out), "+S" (in)
< : "b" (key), "d" (cw)
< : "cc", "memory"
< );
< #endif
< }
---
> MALLOC_DEFINE(M_PADLOCK, "padlock_data", "PadLock Data");
163a76,77
> char capp[256];
>
164a79
> /* If there is no AES support, we has nothing to do here. */
166c81
< printf("PADLOCK: No ACE support.\n");
---
> printf("PadLock: No ACE support.\n");
168,169c83,100
< } else
< printf("PADLOCK: HW support loaded.\n");
---
> }
> strlcpy(capp, "AES-CBC", sizeof(capp));
> #if 0
> strlcat(capp, ",AES-EBC", sizeof(capp));
> strlcat(capp, ",AES-CFB", sizeof(capp));
> strlcat(capp, ",AES-OFB", sizeof(capp));
> #endif
> if (via_feature_xcrypt & VIA_HAS_SHA) {
> strlcat(capp, ",SHA1", sizeof(capp));
> strlcat(capp, ",SHA256", sizeof(capp));
> }
> #if 0
> if (via_feature_xcrypt & VIA_HAS_AESCTR)
> strlcat(capp, ",AES-CTR", sizeof(capp));
> if (via_feature_xcrypt & VIA_HAS_MM)
> strlcat(capp, ",RSA", sizeof(capp));
> #endif
> printf("PadLock: HW support loaded for %s.\n", capp);
174c105
< padlock_sc = sc = malloc(sizeof(*padlock_sc), M_DEVBUF,
---
> padlock_sc = sc = malloc(sizeof(*padlock_sc), M_PADLOCK,
181,182c112,113
< printf("PADLOCK: Could not get crypto driver id.\n");
< free(padlock_sc, M_DEVBUF);
---
> printf("PadLock: Could not get crypto driver id.\n");
> free(padlock_sc, M_PADLOCK);
221c152
< printf("PADLOCK: Cannot destroy, %u sessions active.\n",
---
> printf("PadLock: Cannot destroy, %u sessions active.\n",
229c160
< free(ses, M_DEVBUF);
---
> free(ses, M_PADLOCK);
233c164
< free(sc, M_DEVBUF);
---
> free(sc, M_PADLOCK);
237,287d167
< static void
< padlock_setup_enckey(struct padlock_session *ses, caddr_t key, int klen)
< {
< union padlock_cw *cw;
< int i;
<
< cw = &ses->ses_cw;
< if (cw->cw_key_generation == PADLOCK_KEY_GENERATION_SW) {
< /* Build expanded keys for both directions */
< rijndaelKeySetupEnc(ses->ses_ekey, key, klen);
< rijndaelKeySetupDec(ses->ses_dkey, key, klen);
< for (i = 0; i < 4 * (RIJNDAEL_MAXNR + 1); i++) {
< ses->ses_ekey[i] = ntohl(ses->ses_ekey[i]);
< ses->ses_dkey[i] = ntohl(ses->ses_dkey[i]);
< }
< } else {
< bcopy(key, ses->ses_ekey, klen);
< bcopy(key, ses->ses_dkey, klen);
< }
< }
<
< static void
< padlock_setup_mackey(struct padlock_session *ses, caddr_t key, int klen)
< {
< struct auth_hash *axf;
< int i;
<
< klen /= 8;
< axf = ses->ses_axf;
<
< for (i = 0; i < klen; i++)
< key[i] ^= HMAC_IPAD_VAL;
<
< axf->Init(ses->ses_ictx);
< axf->Update(ses->ses_ictx, key, klen);
< axf->Update(ses->ses_ictx, hmac_ipad_buffer, axf->blocksize - klen);
<
< for (i = 0; i < klen; i++)
< key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
<
< axf->Init(ses->ses_octx);
< axf->Update(ses->ses_octx, key, klen);
< axf->Update(ses->ses_octx, hmac_opad_buffer, axf->blocksize - klen);
<
< for (i = 0; i < klen; i++)
< key[i] ^= HMAC_OPAD_VAL;
< }
<
< /*
< * Compute keyed-hash authenticator.
< */
289,318d168
< padlock_authcompute(struct padlock_session *ses, struct cryptodesc *crd,
< caddr_t buf, int flags)
< {
< u_char hash[HASH_MAX_LEN];
< struct auth_hash *axf;
< union authctx ctx;
< int error;
<
< axf = ses->ses_axf;
<
< bcopy(ses->ses_ictx, &ctx, axf->ctxsize);
<
< error = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len,
< (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx);
< if (error != 0)
< return (error);
<
< axf->Final(hash, &ctx);
< bcopy(ses->ses_octx, &ctx, axf->ctxsize);
< axf->Update(&ctx, hash, axf->hashsize);
< axf->Final(hash, &ctx);
<
< /* Inject the authentication data */
< crypto_copyback(flags, buf, crd->crd_inject,
< ses->ses_mlen == 0 ? axf->hashsize : ses->ses_mlen, hash);
< return (0);
< }
<
<
< static int
324c174
< union padlock_cw *cw;
---
> int error;
360,363d209
< if (encini->cri_klen != 128 && encini->cri_klen != 192 &&
< encini->cri_klen != 256) {
< return (EINVAL);
< }
383c229
< ses = malloc(sizeof(*ses), M_DEVBUF, M_NOWAIT | M_ZERO);
---
> ses = malloc(sizeof(*ses), M_PADLOCK, M_NOWAIT | M_ZERO);
393,414c239,242
< cw = &ses->ses_cw;
< bzero(cw, sizeof(*cw));
< cw->cw_algorithm_type = PADLOCK_ALGORITHM_TYPE_AES;
< cw->cw_key_generation = PADLOCK_KEY_GENERATION_SW;
< cw->cw_intermediate = 0;
< switch (encini->cri_klen) {
< case 128:
< cw->cw_round_count = PADLOCK_ROUND_COUNT_AES128;
< cw->cw_key_size = PADLOCK_KEY_SIZE_128;
< #ifdef HW_KEY_GENERATION
< /* This doesn't buy us much, that's why it is commented out. */
< cw->cw_key_generation = PADLOCK_KEY_GENERATION_HW;
< #endif
< break;
< case 192:
< cw->cw_round_count = PADLOCK_ROUND_COUNT_AES192;
< cw->cw_key_size = PADLOCK_KEY_SIZE_192;
< break;
< case 256:
< cw->cw_round_count = PADLOCK_ROUND_COUNT_AES256;
< cw->cw_key_size = PADLOCK_KEY_SIZE_256;
< break;
---
> error = padlock_cipher_setup(ses, encini);
> if (error != 0) {
> padlock_freesession(NULL, ses->ses_id);
> return (error);
416,417d243
< if (encini->cri_key != NULL)
< padlock_setup_enckey(ses, encini->cri_key, encini->cri_klen);
419,420d244
< arc4rand(ses->ses_iv, sizeof(ses->ses_iv), 0);
<
422,454c246,247
< ses->ses_mlen = macini->cri_mlen;
<
< /* Find software structure which describes HMAC algorithm. */
< switch (macini->cri_alg) {
< case CRYPTO_NULL_HMAC:
< ses->ses_axf = &auth_hash_null;
< break;
< case CRYPTO_MD5_HMAC:
< ses->ses_axf = &auth_hash_hmac_md5;
< break;
< case CRYPTO_SHA1_HMAC:
< ses->ses_axf = &auth_hash_hmac_sha1;
< break;
< case CRYPTO_RIPEMD160_HMAC:
< ses->ses_axf = &auth_hash_hmac_ripemd_160;
< break;
< case CRYPTO_SHA2_256_HMAC:
< ses->ses_axf = &auth_hash_hmac_sha2_256;
< break;
< case CRYPTO_SHA2_384_HMAC:
< ses->ses_axf = &auth_hash_hmac_sha2_384;
< break;
< case CRYPTO_SHA2_512_HMAC:
< ses->ses_axf = &auth_hash_hmac_sha2_512;
< break;
< }
<
< /* Allocate memory for HMAC inner and outer contexts. */
< ses->ses_ictx = malloc(ses->ses_axf->ctxsize, M_CRYPTO_DATA,
< M_NOWAIT);
< ses->ses_octx = malloc(ses->ses_axf->ctxsize, M_CRYPTO_DATA,
< M_NOWAIT);
< if (ses->ses_ictx == NULL || ses->ses_octx == NULL) {
---
> error = padlock_hash_setup(ses, macini);
> if (error != 0) {
456c249
< return (ENOMEM);
---
> return (error);
458,463d250
<
< /* Setup key if given. */
< if (macini->cri_key != NULL) {
< padlock_setup_mackey(ses, macini->cri_key,
< macini->cri_klen);
< }
489,498c276
< if (ses->ses_ictx != NULL) {
< bzero(ses->ses_ictx, ses->ses_axf->ctxsize);
< free(ses->ses_ictx, M_CRYPTO_DATA);
< ses->ses_ictx = NULL;
< }
< if (ses->ses_octx != NULL) {
< bzero(ses->ses_ictx, ses->ses_axf->ctxsize);
< free(ses->ses_octx, M_CRYPTO_DATA);
< ses->ses_octx = NULL;
< }
---
> padlock_hash_free(ses);
510,511c288
< struct padlock_session *ses;
< union padlock_cw *cw;
---
> struct padlock_session *ses = NULL;
513,514d289
< uint32_t *key;
< u_char *buf, *abuf;
518d292
< buf = NULL;
567,605d340
< buf = malloc(enccrd->crd_len + 16, M_DEVBUF, M_NOWAIT);
< if (buf == NULL) {
< error = ENOMEM;
< goto out;
< }
< /* Buffer has to be 16 bytes aligned. */
< abuf = buf + 16 - ((uintptr_t)buf % 16);
<
< if ((enccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0)
< padlock_setup_enckey(ses, enccrd->crd_key, enccrd->crd_klen);
< if (maccrd != NULL && (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0)
< padlock_setup_mackey(ses, maccrd->crd_key, maccrd->crd_klen);
<
< cw = &ses->ses_cw;
< cw->cw_filler0 = 0;
< cw->cw_filler1 = 0;
< cw->cw_filler2 = 0;
< cw->cw_filler3 = 0;
< if ((enccrd->crd_flags & CRD_F_ENCRYPT) != 0) {
< cw->cw_direction = PADLOCK_DIRECTION_ENCRYPT;
< key = ses->ses_ekey;
< if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
< bcopy(enccrd->crd_iv, ses->ses_iv, 16);
<
< if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
< crypto_copyback(crp->crp_flags, crp->crp_buf,
< enccrd->crd_inject, AES_BLOCK_LEN, ses->ses_iv);
< }
< } else {
< cw->cw_direction = PADLOCK_DIRECTION_DECRYPT;
< key = ses->ses_dkey;
< if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
< bcopy(enccrd->crd_iv, ses->ses_iv, AES_BLOCK_LEN);
< else {
< crypto_copydata(crp->crp_flags, crp->crp_buf,
< enccrd->crd_inject, AES_BLOCK_LEN, ses->ses_iv);
< }
< }
<
608,609c343
< error = padlock_authcompute(ses, maccrd, crp->crp_buf,
< crp->crp_flags);
---
> error = padlock_hash_process(ses, maccrd, crp);
614,615c348,350
< crypto_copydata(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
< enccrd->crd_len, abuf);
---
> error = padlock_cipher_process(ses, enccrd, crp);
> if (error != 0)
> goto out;
617,621d351
< padlock_cbc(abuf, abuf, enccrd->crd_len / 16, key, cw, ses->ses_iv);
<
< crypto_copyback(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
< enccrd->crd_len, abuf);
<
624,625c354
< error = padlock_authcompute(ses, maccrd, crp->crp_buf,
< crp->crp_flags);
---
> error = padlock_hash_process(ses, maccrd, crp);
630,636d358
< /* copy out last block for use as next session IV */
< if ((enccrd->crd_flags & CRD_F_ENCRYPT) != 0) {
< crypto_copydata(crp->crp_flags, crp->crp_buf,
< enccrd->crd_skip + enccrd->crd_len - AES_BLOCK_LEN,
< AES_BLOCK_LEN, ses->ses_iv);
< }
<
638,640c360,368
< if (buf != NULL) {
< bzero(buf, enccrd->crd_len + 16);
< free(buf, M_DEVBUF);
---
> #if 0
> /*
> * This code is not necessary, because contexts will be freed on next
> * padlock_setup_mackey() call or at padlock_freesession() call.
> */
> if (ses != NULL && maccrd != NULL &&
> (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) {
> padlock_free_ctx(ses->ses_axf, ses->ses_ictx);
> padlock_free_ctx(ses->ses_axf, ses->ses_octx);
641a370
> #endif