Index: head/sys/crypto/aesni/aesni.c =================================================================== --- head/sys/crypto/aesni/aesni.c (revision 362027) +++ head/sys/crypto/aesni/aesni.c (revision 362028) @@ -1,906 +1,906 @@ /*- * Copyright (c) 2005-2008 Pawel Jakub Dawidek * Copyright (c) 2010 Konstantin Belousov * Copyright (c) 2014 The FreeBSD Foundation * Copyright (c) 2017 Conrad Meyer * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__i386__) #include #elif defined(__amd64__) #include #endif static struct mtx_padalign *ctx_mtx; static struct fpu_kern_ctx **ctx_fpu; struct aesni_softc { int32_t cid; bool has_aes; bool has_sha; }; #define ACQUIRE_CTX(i, ctx) \ do { \ (i) = PCPU_GET(cpuid); \ mtx_lock(&ctx_mtx[(i)]); \ (ctx) = ctx_fpu[(i)]; \ } while (0) #define RELEASE_CTX(i, ctx) \ do { \ mtx_unlock(&ctx_mtx[(i)]); \ (i) = -1; \ (ctx) = NULL; \ } while (0) static int aesni_cipher_setup(struct aesni_session *ses, const struct crypto_session_params *csp); static int aesni_cipher_process(struct aesni_session *ses, struct cryptop *crp); static int aesni_cipher_crypt(struct aesni_session *ses, struct cryptop *crp, const struct crypto_session_params *csp); static int aesni_cipher_mac(struct aesni_session *ses, struct cryptop *crp, const struct crypto_session_params *csp); MALLOC_DEFINE(M_AESNI, "aesni_data", "AESNI Data"); static void aesni_identify(driver_t *drv, device_t parent) { /* NB: order 10 is so we get attached after h/w devices */ if (device_find_child(parent, "aesni", -1) == NULL && BUS_ADD_CHILD(parent, 10, "aesni", -1) == 0) panic("aesni: could not attach"); } static void detect_cpu_features(bool *has_aes, bool *has_sha) { *has_aes = ((cpu_feature2 & CPUID2_AESNI) != 0 && (cpu_feature2 & CPUID2_SSE41) != 0); *has_sha = ((cpu_stdext_feature & CPUID_STDEXT_SHA) != 0 && (cpu_feature2 & CPUID2_SSSE3) != 0); } static int aesni_probe(device_t dev) { bool has_aes, has_sha; detect_cpu_features(&has_aes, &has_sha); if (!has_aes && !has_sha) { device_printf(dev, "No AES or SHA support.\n"); return (EINVAL); } else if (has_aes && has_sha) device_set_desc(dev, "AES-CBC,AES-CCM,AES-GCM,AES-ICM,AES-XTS,SHA1,SHA256"); else if (has_aes) device_set_desc(dev, "AES-CBC,AES-CCM,AES-GCM,AES-ICM,AES-XTS"); else device_set_desc(dev, "SHA1,SHA256"); return (0); } static void aesni_cleanctx(void) { int i; /* XXX - no way to return driverid */ CPU_FOREACH(i) { if (ctx_fpu[i] != NULL) { mtx_destroy(&ctx_mtx[i]); fpu_kern_free_ctx(ctx_fpu[i]); } ctx_fpu[i] = NULL; } free(ctx_mtx, M_AESNI); ctx_mtx = NULL; free(ctx_fpu, M_AESNI); ctx_fpu = NULL; } static int aesni_attach(device_t dev) { struct aesni_softc *sc; int i; sc = device_get_softc(dev); sc->cid = crypto_get_driverid(dev, sizeof(struct aesni_session), CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC | CRYPTOCAP_F_ACCEL_SOFTWARE); if (sc->cid < 0) { device_printf(dev, "Could not get crypto driver id.\n"); return (ENOMEM); } ctx_mtx = malloc(sizeof *ctx_mtx * (mp_maxid + 1), M_AESNI, M_WAITOK|M_ZERO); ctx_fpu = malloc(sizeof *ctx_fpu * (mp_maxid + 1), M_AESNI, M_WAITOK|M_ZERO); CPU_FOREACH(i) { ctx_fpu[i] = fpu_kern_alloc_ctx(0); mtx_init(&ctx_mtx[i], "anifpumtx", NULL, MTX_DEF|MTX_NEW); } detect_cpu_features(&sc->has_aes, &sc->has_sha); return (0); } static int aesni_detach(device_t dev) { struct aesni_softc *sc; sc = device_get_softc(dev); crypto_unregister_all(sc->cid); aesni_cleanctx(); return (0); } static bool aesni_auth_supported(struct aesni_softc *sc, const struct crypto_session_params *csp) { if (!sc->has_sha) return (false); switch (csp->csp_auth_alg) { case CRYPTO_SHA1: case CRYPTO_SHA2_224: case CRYPTO_SHA2_256: case CRYPTO_SHA1_HMAC: case CRYPTO_SHA2_224_HMAC: case CRYPTO_SHA2_256_HMAC: break; default: return (false); } return (true); } static bool aesni_cipher_supported(struct aesni_softc *sc, const struct crypto_session_params *csp) { if (!sc->has_aes) return (false); switch (csp->csp_cipher_alg) { case CRYPTO_AES_CBC: case CRYPTO_AES_ICM: if (csp->csp_ivlen != AES_BLOCK_LEN) return (false); return (sc->has_aes); case CRYPTO_AES_XTS: if (csp->csp_ivlen != AES_XTS_IV_LEN) return (false); return (sc->has_aes); default: return (false); } } static int aesni_probesession(device_t dev, const struct crypto_session_params *csp) { struct aesni_softc *sc; sc = device_get_softc(dev); if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT)) != 0) return (EINVAL); switch (csp->csp_mode) { case CSP_MODE_DIGEST: if (!aesni_auth_supported(sc, csp)) return (EINVAL); break; case CSP_MODE_CIPHER: if (!aesni_cipher_supported(sc, csp)) return (EINVAL); break; case CSP_MODE_AEAD: switch (csp->csp_cipher_alg) { case CRYPTO_AES_NIST_GCM_16: if (csp->csp_auth_mlen != 0 && csp->csp_auth_mlen != GMAC_DIGEST_LEN) return (EINVAL); if (csp->csp_ivlen != AES_GCM_IV_LEN || !sc->has_aes) return (EINVAL); break; case CRYPTO_AES_CCM_16: if (csp->csp_auth_mlen != 0 && csp->csp_auth_mlen != AES_CBC_MAC_HASH_LEN) return (EINVAL); if (csp->csp_ivlen != AES_CCM_IV_LEN || !sc->has_aes) return (EINVAL); break; default: return (EINVAL); } break; case CSP_MODE_ETA: if (!aesni_auth_supported(sc, csp) || !aesni_cipher_supported(sc, csp)) return (EINVAL); break; default: return (EINVAL); } return (CRYPTODEV_PROBE_ACCEL_SOFTWARE); } static int aesni_newsession(device_t dev, crypto_session_t cses, const struct crypto_session_params *csp) { struct aesni_softc *sc; struct aesni_session *ses; int error; sc = device_get_softc(dev); ses = crypto_get_driver_session(cses); switch (csp->csp_mode) { case CSP_MODE_DIGEST: case CSP_MODE_CIPHER: case CSP_MODE_AEAD: case CSP_MODE_ETA: break; default: return (EINVAL); } error = aesni_cipher_setup(ses, csp); if (error != 0) { CRYPTDEB("setup failed"); return (error); } return (0); } static int aesni_process(device_t dev, struct cryptop *crp, int hint __unused) { struct aesni_session *ses; int error; ses = crypto_get_driver_session(crp->crp_session); error = aesni_cipher_process(ses, crp); crp->crp_etype = error; crypto_done(crp); return (0); } static uint8_t * aesni_cipher_alloc(struct cryptop *crp, int start, int length, bool *allocated) { uint8_t *addr; addr = crypto_contiguous_subsegment(crp, start, length); if (addr != NULL) { *allocated = false; return (addr); } addr = malloc(length, M_AESNI, M_NOWAIT); if (addr != NULL) { *allocated = true; crypto_copydata(crp, start, length, addr); } else *allocated = false; return (addr); } static device_method_t aesni_methods[] = { DEVMETHOD(device_identify, aesni_identify), DEVMETHOD(device_probe, aesni_probe), DEVMETHOD(device_attach, aesni_attach), DEVMETHOD(device_detach, aesni_detach), DEVMETHOD(cryptodev_probesession, aesni_probesession), DEVMETHOD(cryptodev_newsession, aesni_newsession), DEVMETHOD(cryptodev_process, aesni_process), DEVMETHOD_END }; static driver_t aesni_driver = { "aesni", aesni_methods, sizeof(struct aesni_softc), }; static devclass_t aesni_devclass; DRIVER_MODULE(aesni, nexus, aesni_driver, aesni_devclass, 0, 0); MODULE_VERSION(aesni, 1); MODULE_DEPEND(aesni, crypto, 1, 1, 1); static int -intel_sha1_update(void *vctx, void *vdata, u_int datalen) +intel_sha1_update(void *vctx, const void *vdata, u_int datalen) { struct sha1_ctxt *ctx = vctx; const char *data = vdata; size_t gaplen; size_t gapstart; size_t off; size_t copysiz; u_int blocks; off = 0; /* Do any aligned blocks without redundant copying. */ if (datalen >= 64 && ctx->count % 64 == 0) { blocks = datalen / 64; ctx->c.b64[0] += blocks * 64 * 8; intel_sha1_step(ctx->h.b32, data + off, blocks); off += blocks * 64; } while (off < datalen) { gapstart = ctx->count % 64; gaplen = 64 - gapstart; copysiz = (gaplen < datalen - off) ? gaplen : datalen - off; bcopy(&data[off], &ctx->m.b8[gapstart], copysiz); ctx->count += copysiz; ctx->count %= 64; ctx->c.b64[0] += copysiz * 8; if (ctx->count % 64 == 0) intel_sha1_step(ctx->h.b32, (void *)ctx->m.b8, 1); off += copysiz; } return (0); } static void SHA1_Init_fn(void *ctx) { sha1_init(ctx); } static void SHA1_Finalize_fn(void *digest, void *ctx) { sha1_result(ctx, digest); } static int -intel_sha256_update(void *vctx, void *vdata, u_int len) +intel_sha256_update(void *vctx, const void *vdata, u_int len) { SHA256_CTX *ctx = vctx; uint64_t bitlen; uint32_t r; u_int blocks; const unsigned char *src = vdata; /* Number of bytes left in the buffer from previous updates */ r = (ctx->count >> 3) & 0x3f; /* Convert the length into a number of bits */ bitlen = len << 3; /* Update number of bits */ ctx->count += bitlen; /* Handle the case where we don't need to perform any transforms */ if (len < 64 - r) { memcpy(&ctx->buf[r], src, len); return (0); } /* Finish the current block */ memcpy(&ctx->buf[r], src, 64 - r); intel_sha256_step(ctx->state, ctx->buf, 1); src += 64 - r; len -= 64 - r; /* Perform complete blocks */ if (len >= 64) { blocks = len / 64; intel_sha256_step(ctx->state, src, blocks); src += blocks * 64; len -= blocks * 64; } /* Copy left over data into buffer */ memcpy(ctx->buf, src, len); return (0); } static void SHA224_Init_fn(void *ctx) { SHA224_Init(ctx); } static void SHA224_Finalize_fn(void *digest, void *ctx) { SHA224_Final(digest, ctx); } static void SHA256_Init_fn(void *ctx) { SHA256_Init(ctx); } static void SHA256_Finalize_fn(void *digest, void *ctx) { SHA256_Final(digest, ctx); } static int aesni_authprepare(struct aesni_session *ses, int klen) { if (klen > SHA1_BLOCK_LEN) return (EINVAL); if ((ses->hmac && klen == 0) || (!ses->hmac && klen != 0)) return (EINVAL); return (0); } static int aesni_cipherprepare(const struct crypto_session_params *csp) { switch (csp->csp_cipher_alg) { case CRYPTO_AES_ICM: case CRYPTO_AES_NIST_GCM_16: case CRYPTO_AES_CCM_16: case CRYPTO_AES_CBC: switch (csp->csp_cipher_klen * 8) { case 128: case 192: case 256: break; default: CRYPTDEB("invalid CBC/ICM/GCM key length"); return (EINVAL); } break; case CRYPTO_AES_XTS: switch (csp->csp_cipher_klen * 8) { case 256: case 512: break; default: CRYPTDEB("invalid XTS key length"); return (EINVAL); } break; default: return (EINVAL); } return (0); } static int aesni_cipher_setup(struct aesni_session *ses, const struct crypto_session_params *csp) { struct fpu_kern_ctx *ctx; int kt, ctxidx, error; switch (csp->csp_auth_alg) { case CRYPTO_SHA1_HMAC: ses->hmac = true; /* FALLTHROUGH */ case CRYPTO_SHA1: ses->hash_len = SHA1_HASH_LEN; ses->hash_init = SHA1_Init_fn; ses->hash_update = intel_sha1_update; ses->hash_finalize = SHA1_Finalize_fn; break; case CRYPTO_SHA2_224_HMAC: ses->hmac = true; /* FALLTHROUGH */ case CRYPTO_SHA2_224: ses->hash_len = SHA2_224_HASH_LEN; ses->hash_init = SHA224_Init_fn; ses->hash_update = intel_sha256_update; ses->hash_finalize = SHA224_Finalize_fn; break; case CRYPTO_SHA2_256_HMAC: ses->hmac = true; /* FALLTHROUGH */ case CRYPTO_SHA2_256: ses->hash_len = SHA2_256_HASH_LEN; ses->hash_init = SHA256_Init_fn; ses->hash_update = intel_sha256_update; ses->hash_finalize = SHA256_Finalize_fn; break; } if (ses->hash_len != 0) { if (csp->csp_auth_mlen == 0) ses->mlen = ses->hash_len; else ses->mlen = csp->csp_auth_mlen; error = aesni_authprepare(ses, csp->csp_auth_klen); if (error != 0) return (error); } error = aesni_cipherprepare(csp); if (error != 0) return (error); kt = is_fpu_kern_thread(0) || (csp->csp_cipher_alg == 0); if (!kt) { ACQUIRE_CTX(ctxidx, ctx); fpu_kern_enter(curthread, ctx, FPU_KERN_NORMAL | FPU_KERN_KTHR); } error = 0; if (csp->csp_cipher_key != NULL) aesni_cipher_setup_common(ses, csp, csp->csp_cipher_key, csp->csp_cipher_klen); if (!kt) { fpu_kern_leave(curthread, ctx); RELEASE_CTX(ctxidx, ctx); } return (error); } static int aesni_cipher_process(struct aesni_session *ses, struct cryptop *crp) { const struct crypto_session_params *csp; struct fpu_kern_ctx *ctx; int error, ctxidx; bool kt; csp = crypto_get_params(crp->crp_session); switch (csp->csp_cipher_alg) { case CRYPTO_AES_ICM: case CRYPTO_AES_NIST_GCM_16: case CRYPTO_AES_CCM_16: if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) return (EINVAL); break; case CRYPTO_AES_CBC: case CRYPTO_AES_XTS: /* CBC & XTS can only handle full blocks for now */ if ((crp->crp_payload_length % AES_BLOCK_LEN) != 0) return (EINVAL); break; } ctx = NULL; ctxidx = 0; error = 0; kt = is_fpu_kern_thread(0); if (!kt) { ACQUIRE_CTX(ctxidx, ctx); fpu_kern_enter(curthread, ctx, FPU_KERN_NORMAL | FPU_KERN_KTHR); } /* Do work */ if (csp->csp_mode == CSP_MODE_ETA) { if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { error = aesni_cipher_crypt(ses, crp, csp); if (error == 0) error = aesni_cipher_mac(ses, crp, csp); } else { error = aesni_cipher_mac(ses, crp, csp); if (error == 0) error = aesni_cipher_crypt(ses, crp, csp); } } else if (csp->csp_mode == CSP_MODE_DIGEST) error = aesni_cipher_mac(ses, crp, csp); else error = aesni_cipher_crypt(ses, crp, csp); if (!kt) { fpu_kern_leave(curthread, ctx); RELEASE_CTX(ctxidx, ctx); } return (error); } static int aesni_cipher_crypt(struct aesni_session *ses, struct cryptop *crp, const struct crypto_session_params *csp) { uint8_t iv[AES_BLOCK_LEN], tag[GMAC_DIGEST_LEN]; uint8_t *authbuf, *buf, *outbuf; int error; bool encflag, allocated, authallocated, outallocated, outcopy; buf = aesni_cipher_alloc(crp, crp->crp_payload_start, crp->crp_payload_length, &allocated); if (buf == NULL) return (ENOMEM); outallocated = false; authallocated = false; authbuf = NULL; if (csp->csp_cipher_alg == CRYPTO_AES_NIST_GCM_16 || csp->csp_cipher_alg == CRYPTO_AES_CCM_16) { authbuf = aesni_cipher_alloc(crp, crp->crp_aad_start, crp->crp_aad_length, &authallocated); if (authbuf == NULL) { error = ENOMEM; goto out; } } if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { outbuf = crypto_buffer_contiguous_subsegment(&crp->crp_obuf, crp->crp_payload_output_start, crp->crp_payload_length); if (outbuf == NULL) { outcopy = true; if (allocated) outbuf = buf; else { outbuf = malloc(crp->crp_payload_length, M_AESNI, M_NOWAIT); if (outbuf == NULL) { error = ENOMEM; goto out; } outallocated = true; } } else outcopy = false; } else { outbuf = buf; outcopy = allocated; } error = 0; encflag = CRYPTO_OP_IS_ENCRYPT(crp->crp_op); if (crp->crp_cipher_key != NULL) aesni_cipher_setup_common(ses, csp, crp->crp_cipher_key, csp->csp_cipher_klen); crypto_read_iv(crp, iv); switch (csp->csp_cipher_alg) { case CRYPTO_AES_CBC: if (encflag) aesni_encrypt_cbc(ses->rounds, ses->enc_schedule, crp->crp_payload_length, buf, outbuf, iv); else { if (buf != outbuf) memcpy(outbuf, buf, crp->crp_payload_length); aesni_decrypt_cbc(ses->rounds, ses->dec_schedule, crp->crp_payload_length, outbuf, iv); } break; case CRYPTO_AES_ICM: /* encryption & decryption are the same */ aesni_encrypt_icm(ses->rounds, ses->enc_schedule, crp->crp_payload_length, buf, outbuf, iv); break; case CRYPTO_AES_XTS: if (encflag) aesni_encrypt_xts(ses->rounds, ses->enc_schedule, ses->xts_schedule, crp->crp_payload_length, buf, outbuf, iv); else aesni_decrypt_xts(ses->rounds, ses->dec_schedule, ses->xts_schedule, crp->crp_payload_length, buf, outbuf, iv); break; case CRYPTO_AES_NIST_GCM_16: if (encflag) { memset(tag, 0, sizeof(tag)); AES_GCM_encrypt(buf, outbuf, authbuf, iv, tag, crp->crp_payload_length, crp->crp_aad_length, csp->csp_ivlen, ses->enc_schedule, ses->rounds); crypto_copyback(crp, crp->crp_digest_start, sizeof(tag), tag); } else { crypto_copydata(crp, crp->crp_digest_start, sizeof(tag), tag); if (!AES_GCM_decrypt(buf, outbuf, authbuf, iv, tag, crp->crp_payload_length, crp->crp_aad_length, csp->csp_ivlen, ses->enc_schedule, ses->rounds)) error = EBADMSG; } break; case CRYPTO_AES_CCM_16: if (encflag) { memset(tag, 0, sizeof(tag)); AES_CCM_encrypt(buf, outbuf, authbuf, iv, tag, crp->crp_payload_length, crp->crp_aad_length, csp->csp_ivlen, ses->enc_schedule, ses->rounds); crypto_copyback(crp, crp->crp_digest_start, sizeof(tag), tag); } else { crypto_copydata(crp, crp->crp_digest_start, sizeof(tag), tag); if (!AES_CCM_decrypt(buf, outbuf, authbuf, iv, tag, crp->crp_payload_length, crp->crp_aad_length, csp->csp_ivlen, ses->enc_schedule, ses->rounds)) error = EBADMSG; } break; } if (outcopy && error == 0) crypto_copyback(crp, CRYPTO_HAS_OUTPUT_BUFFER(crp) ? crp->crp_payload_output_start : crp->crp_payload_start, crp->crp_payload_length, outbuf); out: if (allocated) { explicit_bzero(buf, crp->crp_payload_length); free(buf, M_AESNI); } if (authallocated) { explicit_bzero(authbuf, crp->crp_aad_length); free(authbuf, M_AESNI); } if (outallocated) { explicit_bzero(outbuf, crp->crp_payload_length); free(outbuf, M_AESNI); } explicit_bzero(iv, sizeof(iv)); explicit_bzero(tag, sizeof(tag)); return (error); } static int aesni_cipher_mac(struct aesni_session *ses, struct cryptop *crp, const struct crypto_session_params *csp) { union { struct SHA256Context sha2 __aligned(16); struct sha1_ctxt sha1 __aligned(16); } sctx; uint32_t res[SHA2_256_HASH_LEN / sizeof(uint32_t)]; const uint8_t *key; int i, keylen; if (crp->crp_auth_key != NULL) key = crp->crp_auth_key; else key = csp->csp_auth_key; keylen = csp->csp_auth_klen; if (ses->hmac) { uint8_t hmac_key[SHA1_BLOCK_LEN] __aligned(16); /* Inner hash: (K ^ IPAD) || data */ ses->hash_init(&sctx); for (i = 0; i < keylen; i++) hmac_key[i] = key[i] ^ HMAC_IPAD_VAL; for (i = keylen; i < sizeof(hmac_key); i++) hmac_key[i] = 0 ^ HMAC_IPAD_VAL; ses->hash_update(&sctx, hmac_key, sizeof(hmac_key)); crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, ses->hash_update, &sctx); if (CRYPTO_HAS_OUTPUT_BUFFER(crp) && CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) crypto_apply_buf(&crp->crp_obuf, crp->crp_payload_output_start, crp->crp_payload_length, ses->hash_update, &sctx); else crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length, ses->hash_update, &sctx); ses->hash_finalize(res, &sctx); /* Outer hash: (K ^ OPAD) || inner hash */ ses->hash_init(&sctx); for (i = 0; i < keylen; i++) hmac_key[i] = key[i] ^ HMAC_OPAD_VAL; for (i = keylen; i < sizeof(hmac_key); i++) hmac_key[i] = 0 ^ HMAC_OPAD_VAL; ses->hash_update(&sctx, hmac_key, sizeof(hmac_key)); ses->hash_update(&sctx, res, ses->hash_len); ses->hash_finalize(res, &sctx); explicit_bzero(hmac_key, sizeof(hmac_key)); } else { ses->hash_init(&sctx); crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, ses->hash_update, &sctx); if (CRYPTO_HAS_OUTPUT_BUFFER(crp) && CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) crypto_apply_buf(&crp->crp_obuf, crp->crp_payload_output_start, crp->crp_payload_length, ses->hash_update, &sctx); else crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length, ses->hash_update, &sctx); ses->hash_finalize(res, &sctx); } if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { uint32_t res2[SHA2_256_HASH_LEN / sizeof(uint32_t)]; crypto_copydata(crp, crp->crp_digest_start, ses->mlen, res2); if (timingsafe_bcmp(res, res2, ses->mlen) != 0) return (EBADMSG); explicit_bzero(res2, sizeof(res2)); } else crypto_copyback(crp, crp->crp_digest_start, ses->mlen, res); explicit_bzero(res, sizeof(res)); return (0); } Index: head/sys/crypto/aesni/aesni.h =================================================================== --- head/sys/crypto/aesni/aesni.h (revision 362027) +++ head/sys/crypto/aesni/aesni.h (revision 362028) @@ -1,126 +1,126 @@ /*- * Copyright (c) 2010 Konstantin Belousov * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _AESNI_H_ #define _AESNI_H_ #include #include #include #include #if defined(__amd64__) || defined(__i386__) #include #include #include #include #endif #if defined(__i386__) #include #elif defined(__amd64__) #include #endif #define AES128_ROUNDS 10 #define AES192_ROUNDS 12 #define AES256_ROUNDS 14 #define AES_SCHED_LEN ((AES256_ROUNDS + 1) * AES_BLOCK_LEN) struct aesni_session { uint8_t enc_schedule[AES_SCHED_LEN] __aligned(16); uint8_t dec_schedule[AES_SCHED_LEN] __aligned(16); uint8_t xts_schedule[AES_SCHED_LEN] __aligned(16); int rounds; /* uint8_t *ses_ictx; */ /* uint8_t *ses_octx; */ int used; int mlen; int hash_len; void (*hash_init)(void *); - int (*hash_update)(void *, void *, unsigned); + int (*hash_update)(void *, const void *, u_int); void (*hash_finalize)(void *, void *); bool hmac; }; /* * Internal functions, implemented in assembler. */ void aesni_set_enckey(const uint8_t *userkey, uint8_t *encrypt_schedule /*__aligned(16)*/, int number_of_rounds); void aesni_set_deckey(const uint8_t *encrypt_schedule /*__aligned(16)*/, uint8_t *decrypt_schedule /*__aligned(16)*/, int number_of_rounds); /* * Slightly more public interfaces. */ void aesni_encrypt_cbc(int rounds, const void *key_schedule /*__aligned(16)*/, size_t len, const uint8_t *from, uint8_t *to, const uint8_t iv[__min_size(AES_BLOCK_LEN)]); void aesni_decrypt_cbc(int rounds, const void *key_schedule /*__aligned(16)*/, size_t len, uint8_t *buf, const uint8_t iv[__min_size(AES_BLOCK_LEN)]); void aesni_encrypt_ecb(int rounds, const void *key_schedule /*__aligned(16)*/, size_t len, const uint8_t *from, uint8_t *to); void aesni_decrypt_ecb(int rounds, const void *key_schedule /*__aligned(16)*/, size_t len, const uint8_t *from, uint8_t *to); void aesni_encrypt_icm(int rounds, const void *key_schedule /*__aligned(16)*/, size_t len, const uint8_t *from, uint8_t *to, const uint8_t iv[__min_size(AES_BLOCK_LEN)]); void aesni_encrypt_xts(int rounds, const void *data_schedule /*__aligned(16)*/, const void *tweak_schedule /*__aligned(16)*/, size_t len, const uint8_t *from, uint8_t *to, const uint8_t iv[__min_size(AES_BLOCK_LEN)]); void aesni_decrypt_xts(int rounds, const void *data_schedule /*__aligned(16)*/, const void *tweak_schedule /*__aligned(16)*/, size_t len, const uint8_t *from, uint8_t *to, const uint8_t iv[__min_size(AES_BLOCK_LEN)]); /* GCM & GHASH functions */ void AES_GCM_encrypt(const unsigned char *in, unsigned char *out, const unsigned char *addt, const unsigned char *ivec, unsigned char *tag, uint32_t nbytes, uint32_t abytes, int ibytes, const unsigned char *key, int nr); int AES_GCM_decrypt(const unsigned char *in, unsigned char *out, const unsigned char *addt, const unsigned char *ivec, const unsigned char *tag, uint32_t nbytes, uint32_t abytes, int ibytes, const unsigned char *key, int nr); /* CCM + CBC-MAC functions */ void AES_CCM_encrypt(const unsigned char *in, unsigned char *out, const unsigned char *addt, const unsigned char *ivec, unsigned char *tag, uint32_t nbytes, uint32_t abytes, int ibytes, const unsigned char *key, int nr); int AES_CCM_decrypt(const unsigned char *in, unsigned char *out, const unsigned char *addt, const unsigned char *ivec, const unsigned char *tag, uint32_t nbytes, uint32_t abytes, int ibytes, const unsigned char *key, int nr); void aesni_cipher_setup_common(struct aesni_session *ses, const struct crypto_session_params *csp, const uint8_t *key, int keylen); #endif /* _AESNI_H_ */ Index: head/sys/crypto/blake2/blake2-sw.c =================================================================== --- head/sys/crypto/blake2/blake2-sw.c (revision 362027) +++ head/sys/crypto/blake2/blake2-sw.c (revision 362028) @@ -1,163 +1,163 @@ /* This file is in the public domain. */ #include __FBSDID("$FreeBSD$"); #include #include extern int blake2b_init_ref(blake2b_state *S, size_t outlen); extern int blake2b_init_param_ref(blake2b_state *S, const blake2b_param *P); extern int blake2b_init_key_ref(blake2b_state *S, size_t outlen, const void *key, size_t keylen); extern int blake2b_update_ref(blake2b_state *S, const uint8_t *in, size_t inlen); extern int blake2b_final_ref(blake2b_state *S, uint8_t *out, size_t outlen); extern int blake2b_ref(uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen); extern int blake2s_init_ref(blake2s_state *S, size_t outlen); extern int blake2s_init_param_ref(blake2s_state *S, const blake2s_param *P); extern int blake2s_init_key_ref(blake2s_state *S, size_t outlen, const void *key, size_t keylen); extern int blake2s_update_ref(blake2s_state *S, const uint8_t *in, size_t inlen); extern int blake2s_final_ref(blake2s_state *S, uint8_t *out, size_t outlen); extern int blake2s_ref(uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen); struct blake2b_xform_ctx { blake2b_state state; uint8_t key[BLAKE2B_KEYBYTES]; uint16_t klen; }; CTASSERT(sizeof(union authctx) >= sizeof(struct blake2b_xform_ctx)); static void blake2b_xform_init(void *vctx) { struct blake2b_xform_ctx *ctx = vctx; int rc; if (ctx->klen > 0) rc = blake2b_init_key_ref(&ctx->state, BLAKE2B_OUTBYTES, ctx->key, ctx->klen); else rc = blake2b_init_ref(&ctx->state, BLAKE2B_OUTBYTES); if (rc != 0) panic("blake2b_init_key: invalid arguments"); } static void -blake2b_xform_setkey(void *vctx, const uint8_t *key, uint16_t klen) +blake2b_xform_setkey(void *vctx, const uint8_t *key, u_int klen) { struct blake2b_xform_ctx *ctx = vctx; if (klen > sizeof(ctx->key)) panic("invalid klen %u", (unsigned)klen); memcpy(ctx->key, key, klen); ctx->klen = klen; } static int -blake2b_xform_update(void *vctx, const uint8_t *data, uint16_t len) +blake2b_xform_update(void *vctx, const void *data, u_int len) { struct blake2b_xform_ctx *ctx = vctx; int rc; rc = blake2b_update_ref(&ctx->state, data, len); if (rc != 0) return (EINVAL); return (0); } static void blake2b_xform_final(uint8_t *out, void *vctx) { struct blake2b_xform_ctx *ctx = vctx; int rc; rc = blake2b_final_ref(&ctx->state, out, BLAKE2B_OUTBYTES); if (rc != 0) panic("blake2b_final: invalid"); } struct auth_hash auth_hash_blake2b = { .type = CRYPTO_BLAKE2B, .name = "Blake2b", .keysize = BLAKE2B_KEYBYTES, .hashsize = BLAKE2B_OUTBYTES, .ctxsize = sizeof(struct blake2b_xform_ctx), .Setkey = blake2b_xform_setkey, .Init = blake2b_xform_init, .Update = blake2b_xform_update, .Final = blake2b_xform_final, }; struct blake2s_xform_ctx { blake2s_state state; uint8_t key[BLAKE2S_KEYBYTES]; uint16_t klen; }; CTASSERT(sizeof(union authctx) >= sizeof(struct blake2s_xform_ctx)); static void blake2s_xform_init(void *vctx) { struct blake2s_xform_ctx *ctx = vctx; int rc; if (ctx->klen > 0) rc = blake2s_init_key_ref(&ctx->state, BLAKE2S_OUTBYTES, ctx->key, ctx->klen); else rc = blake2s_init_ref(&ctx->state, BLAKE2S_OUTBYTES); if (rc != 0) panic("blake2s_init_key: invalid arguments"); } static void -blake2s_xform_setkey(void *vctx, const uint8_t *key, uint16_t klen) +blake2s_xform_setkey(void *vctx, const uint8_t *key, u_int klen) { struct blake2s_xform_ctx *ctx = vctx; if (klen > sizeof(ctx->key)) panic("invalid klen %u", (unsigned)klen); memcpy(ctx->key, key, klen); ctx->klen = klen; } static int -blake2s_xform_update(void *vctx, const uint8_t *data, uint16_t len) +blake2s_xform_update(void *vctx, const void *data, u_int len) { struct blake2s_xform_ctx *ctx = vctx; int rc; rc = blake2s_update_ref(&ctx->state, data, len); if (rc != 0) return (EINVAL); return (0); } static void blake2s_xform_final(uint8_t *out, void *vctx) { struct blake2s_xform_ctx *ctx = vctx; int rc; rc = blake2s_final_ref(&ctx->state, out, BLAKE2S_OUTBYTES); if (rc != 0) panic("blake2s_final: invalid"); } struct auth_hash auth_hash_blake2s = { .type = CRYPTO_BLAKE2S, .name = "Blake2s", .keysize = BLAKE2S_KEYBYTES, .hashsize = BLAKE2S_OUTBYTES, .ctxsize = sizeof(struct blake2s_xform_ctx), .Setkey = blake2s_xform_setkey, .Init = blake2s_xform_init, .Update = blake2s_xform_update, .Final = blake2s_xform_final, }; Index: head/sys/crypto/blake2/blake2_cryptodev.c =================================================================== --- head/sys/crypto/blake2/blake2_cryptodev.c (revision 362027) +++ head/sys/crypto/blake2/blake2_cryptodev.c (revision 362028) @@ -1,413 +1,413 @@ /*- * Copyright (c) 2018 Conrad Meyer * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__amd64__) #include #elif defined(__i386__) #include #endif struct blake2_session { size_t mlen; }; CTASSERT((size_t)BLAKE2B_KEYBYTES > (size_t)BLAKE2S_KEYBYTES); struct blake2_softc { bool dying; int32_t cid; struct rwlock lock; }; static struct mtx_padalign *ctx_mtx; static struct fpu_kern_ctx **ctx_fpu; #define ACQUIRE_CTX(i, ctx) \ do { \ (i) = PCPU_GET(cpuid); \ mtx_lock(&ctx_mtx[(i)]); \ (ctx) = ctx_fpu[(i)]; \ } while (0) #define RELEASE_CTX(i, ctx) \ do { \ mtx_unlock(&ctx_mtx[(i)]); \ (i) = -1; \ (ctx) = NULL; \ } while (0) static int blake2_cipher_setup(struct blake2_session *ses, const struct crypto_session_params *csp); static int blake2_cipher_process(struct blake2_session *ses, struct cryptop *crp); MALLOC_DEFINE(M_BLAKE2, "blake2_data", "Blake2 Data"); static void blake2_identify(driver_t *drv, device_t parent) { /* NB: order 10 is so we get attached after h/w devices */ if (device_find_child(parent, "blaketwo", -1) == NULL && BUS_ADD_CHILD(parent, 10, "blaketwo", -1) == 0) panic("blaketwo: could not attach"); } static int blake2_probe(device_t dev) { device_set_desc(dev, "Blake2"); return (0); } static void blake2_cleanctx(void) { int i; /* XXX - no way to return driverid */ CPU_FOREACH(i) { if (ctx_fpu[i] != NULL) { mtx_destroy(&ctx_mtx[i]); fpu_kern_free_ctx(ctx_fpu[i]); } ctx_fpu[i] = NULL; } free(ctx_mtx, M_BLAKE2); ctx_mtx = NULL; free(ctx_fpu, M_BLAKE2); ctx_fpu = NULL; } static int blake2_attach(device_t dev) { struct blake2_softc *sc; int i; sc = device_get_softc(dev); sc->dying = false; sc->cid = crypto_get_driverid(dev, sizeof(struct blake2_session), CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC | CRYPTOCAP_F_ACCEL_SOFTWARE); if (sc->cid < 0) { device_printf(dev, "Could not get crypto driver id.\n"); return (ENOMEM); } ctx_mtx = malloc(sizeof(*ctx_mtx) * (mp_maxid + 1), M_BLAKE2, M_WAITOK | M_ZERO); ctx_fpu = malloc(sizeof(*ctx_fpu) * (mp_maxid + 1), M_BLAKE2, M_WAITOK | M_ZERO); CPU_FOREACH(i) { ctx_fpu[i] = fpu_kern_alloc_ctx(0); mtx_init(&ctx_mtx[i], "bl2fpumtx", NULL, MTX_DEF | MTX_NEW); } rw_init(&sc->lock, "blake2_lock"); return (0); } static int blake2_detach(device_t dev) { struct blake2_softc *sc; sc = device_get_softc(dev); rw_wlock(&sc->lock); sc->dying = true; rw_wunlock(&sc->lock); crypto_unregister_all(sc->cid); rw_destroy(&sc->lock); blake2_cleanctx(); return (0); } static int blake2_probesession(device_t dev, const struct crypto_session_params *csp) { if (csp->csp_flags != 0) return (EINVAL); switch (csp->csp_mode) { case CSP_MODE_DIGEST: switch (csp->csp_auth_alg) { case CRYPTO_BLAKE2B: case CRYPTO_BLAKE2S: break; default: return (EINVAL); } break; default: return (EINVAL); } return (CRYPTODEV_PROBE_ACCEL_SOFTWARE); } static int blake2_newsession(device_t dev, crypto_session_t cses, const struct crypto_session_params *csp) { struct blake2_softc *sc; struct blake2_session *ses; int error; sc = device_get_softc(dev); ses = crypto_get_driver_session(cses); rw_rlock(&sc->lock); if (sc->dying) { rw_runlock(&sc->lock); return (EINVAL); } rw_runlock(&sc->lock); error = blake2_cipher_setup(ses, csp); if (error != 0) { CRYPTDEB("setup failed"); return (error); } return (0); } static int blake2_process(device_t dev, struct cryptop *crp, int hint __unused) { struct blake2_session *ses; int error; ses = crypto_get_driver_session(crp->crp_session); error = blake2_cipher_process(ses, crp); crp->crp_etype = error; crypto_done(crp); return (0); } static device_method_t blake2_methods[] = { DEVMETHOD(device_identify, blake2_identify), DEVMETHOD(device_probe, blake2_probe), DEVMETHOD(device_attach, blake2_attach), DEVMETHOD(device_detach, blake2_detach), DEVMETHOD(cryptodev_probesession, blake2_probesession), DEVMETHOD(cryptodev_newsession, blake2_newsession), DEVMETHOD(cryptodev_process, blake2_process), DEVMETHOD_END }; static driver_t blake2_driver = { "blaketwo", blake2_methods, sizeof(struct blake2_softc), }; static devclass_t blake2_devclass; DRIVER_MODULE(blake2, nexus, blake2_driver, blake2_devclass, 0, 0); MODULE_VERSION(blake2, 1); MODULE_DEPEND(blake2, crypto, 1, 1, 1); static bool blake2_check_klen(const struct crypto_session_params *csp, unsigned klen) { if (csp->csp_auth_alg == CRYPTO_BLAKE2S) return (klen <= BLAKE2S_KEYBYTES); else return (klen <= BLAKE2B_KEYBYTES); } static int blake2_cipher_setup(struct blake2_session *ses, const struct crypto_session_params *csp) { int hashlen; CTASSERT((size_t)BLAKE2S_OUTBYTES <= (size_t)BLAKE2B_OUTBYTES); if (!blake2_check_klen(csp, csp->csp_auth_klen)) return (EINVAL); if (csp->csp_auth_mlen < 0) return (EINVAL); switch (csp->csp_auth_alg) { case CRYPTO_BLAKE2S: hashlen = BLAKE2S_OUTBYTES; break; case CRYPTO_BLAKE2B: hashlen = BLAKE2B_OUTBYTES; break; default: return (EINVAL); } if (csp->csp_auth_mlen > hashlen) return (EINVAL); if (csp->csp_auth_mlen == 0) ses->mlen = hashlen; else ses->mlen = csp->csp_auth_mlen; return (0); } static int -blake2b_applicator(void *state, void *buf, u_int len) +blake2b_applicator(void *state, const void *buf, u_int len) { int rc; rc = blake2b_update(state, buf, len); if (rc != 0) return (EINVAL); return (0); } static int -blake2s_applicator(void *state, void *buf, u_int len) +blake2s_applicator(void *state, const void *buf, u_int len) { int rc; rc = blake2s_update(state, buf, len); if (rc != 0) return (EINVAL); return (0); } static int blake2_cipher_process(struct blake2_session *ses, struct cryptop *crp) { union { blake2b_state sb; blake2s_state ss; } bctx; char res[BLAKE2B_OUTBYTES], res2[BLAKE2B_OUTBYTES]; const struct crypto_session_params *csp; struct fpu_kern_ctx *ctx; const void *key; int ctxidx; bool kt; int error, rc; unsigned klen; ctx = NULL; ctxidx = 0; error = EINVAL; kt = is_fpu_kern_thread(0); if (!kt) { ACQUIRE_CTX(ctxidx, ctx); fpu_kern_enter(curthread, ctx, FPU_KERN_NORMAL | FPU_KERN_KTHR); } csp = crypto_get_params(crp->crp_session); if (crp->crp_auth_key != NULL) key = crp->crp_auth_key; else key = csp->csp_auth_key; klen = csp->csp_auth_klen; switch (csp->csp_auth_alg) { case CRYPTO_BLAKE2B: if (klen > 0) rc = blake2b_init_key(&bctx.sb, ses->mlen, key, klen); else rc = blake2b_init(&bctx.sb, ses->mlen); if (rc != 0) goto out; error = crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length, blake2b_applicator, &bctx.sb); if (error != 0) goto out; rc = blake2b_final(&bctx.sb, res, ses->mlen); if (rc != 0) { error = EINVAL; goto out; } break; case CRYPTO_BLAKE2S: if (klen > 0) rc = blake2s_init_key(&bctx.ss, ses->mlen, key, klen); else rc = blake2s_init(&bctx.ss, ses->mlen); if (rc != 0) goto out; error = crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length, blake2s_applicator, &bctx.ss); if (error != 0) goto out; rc = blake2s_final(&bctx.ss, res, ses->mlen); if (rc != 0) { error = EINVAL; goto out; } break; default: panic("unreachable"); } if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { crypto_copydata(crp, crp->crp_digest_start, ses->mlen, res2); if (timingsafe_bcmp(res, res2, ses->mlen) != 0) return (EBADMSG); } else crypto_copyback(crp, crp->crp_digest_start, ses->mlen, res); out: if (!kt) { fpu_kern_leave(curthread, ctx); RELEASE_CTX(ctxidx, ctx); } return (error); } Index: head/sys/crypto/via/padlock_hash.c =================================================================== --- head/sys/crypto/via/padlock_hash.c (revision 362027) +++ head/sys/crypto/via/padlock_hash.c (revision 362028) @@ -1,420 +1,428 @@ /*- * Copyright (c) 2006 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #if defined(__amd64__) || defined(__i386__) #include #include #include #include #endif #include #include #include #include /* * Implementation notes. * * Some VIA CPUs provides SHA1 and SHA256 acceleration. * We implement all HMAC algorithms provided by crypto(9) framework, but we do * the crypto work in software unless this is HMAC/SHA1 or HMAC/SHA256 and * our CPU can accelerate it. * * Additional CPU instructions, which preform SHA1 and SHA256 are one-shot * functions - we have only one chance to give the data, CPU itself will add * the padding and calculate hash automatically. * This means, it is not possible to implement common init(), update(), final() * methods. * The way I've choosen is to keep adding data to the buffer on update() * (reallocating the buffer if necessary) and call XSHA{1,256} instruction on * final(). */ struct padlock_sha_ctx { uint8_t *psc_buf; int psc_offset; int psc_size; }; CTASSERT(sizeof(struct padlock_sha_ctx) <= sizeof(union authctx)); -static void padlock_sha_init(struct padlock_sha_ctx *ctx); -static int padlock_sha_update(struct padlock_sha_ctx *ctx, const uint8_t *buf, - uint16_t bufsize); -static void padlock_sha1_final(uint8_t *hash, struct padlock_sha_ctx *ctx); -static void padlock_sha256_final(uint8_t *hash, struct padlock_sha_ctx *ctx); +static void padlock_sha_init(void *vctx); +static int padlock_sha_update(void *vctx, const void *buf, u_int bufsize); +static void padlock_sha1_final(uint8_t *hash, void *vctx); +static void padlock_sha256_final(uint8_t *hash, void *vctx); static struct auth_hash padlock_hmac_sha1 = { .type = CRYPTO_SHA1_HMAC, .name = "HMAC-SHA1", .keysize = SHA1_BLOCK_LEN, .hashsize = SHA1_HASH_LEN, .ctxsize = sizeof(struct padlock_sha_ctx), .blocksize = SHA1_BLOCK_LEN, - .Init = (void (*)(void *))padlock_sha_init, - .Update = (int (*)(void *, const uint8_t *, uint16_t))padlock_sha_update, - .Final = (void (*)(uint8_t *, void *))padlock_sha1_final, + .Init = padlock_sha_init, + .Update = padlock_sha_update, + .Final = padlock_sha1_final, }; static struct auth_hash padlock_hmac_sha256 = { .type = CRYPTO_SHA2_256_HMAC, .name = "HMAC-SHA2-256", .keysize = SHA2_256_BLOCK_LEN, .hashsize = SHA2_256_HASH_LEN, .ctxsize = sizeof(struct padlock_sha_ctx), .blocksize = SHA2_256_BLOCK_LEN, - .Init = (void (*)(void *))padlock_sha_init, - .Update = (int (*)(void *, const uint8_t *, uint16_t))padlock_sha_update, - .Final = (void (*)(uint8_t *, void *))padlock_sha256_final, + .Init = padlock_sha_init, + .Update = padlock_sha_update, + .Final = padlock_sha256_final, }; MALLOC_DECLARE(M_PADLOCK); static __inline void padlock_output_block(uint32_t *src, uint32_t *dst, size_t count) { while (count-- > 0) *dst++ = bswap32(*src++); } static void padlock_do_sha1(const u_char *in, u_char *out, int count) { u_char buf[128+16]; /* PadLock needs at least 128 bytes buffer. */ u_char *result = PADLOCK_ALIGN(buf); ((uint32_t *)result)[0] = 0x67452301; ((uint32_t *)result)[1] = 0xEFCDAB89; ((uint32_t *)result)[2] = 0x98BADCFE; ((uint32_t *)result)[3] = 0x10325476; ((uint32_t *)result)[4] = 0xC3D2E1F0; #ifdef __GNUCLIKE_ASM __asm __volatile( ".byte 0xf3, 0x0f, 0xa6, 0xc8" /* rep xsha1 */ : "+S"(in), "+D"(result) : "c"(count), "a"(0) ); #endif padlock_output_block((uint32_t *)result, (uint32_t *)out, SHA1_HASH_LEN / sizeof(uint32_t)); } static void padlock_do_sha256(const char *in, char *out, int count) { char buf[128+16]; /* PadLock needs at least 128 bytes buffer. */ char *result = PADLOCK_ALIGN(buf); ((uint32_t *)result)[0] = 0x6A09E667; ((uint32_t *)result)[1] = 0xBB67AE85; ((uint32_t *)result)[2] = 0x3C6EF372; ((uint32_t *)result)[3] = 0xA54FF53A; ((uint32_t *)result)[4] = 0x510E527F; ((uint32_t *)result)[5] = 0x9B05688C; ((uint32_t *)result)[6] = 0x1F83D9AB; ((uint32_t *)result)[7] = 0x5BE0CD19; #ifdef __GNUCLIKE_ASM __asm __volatile( ".byte 0xf3, 0x0f, 0xa6, 0xd0" /* rep xsha256 */ : "+S"(in), "+D"(result) : "c"(count), "a"(0) ); #endif padlock_output_block((uint32_t *)result, (uint32_t *)out, SHA2_256_HASH_LEN / sizeof(uint32_t)); } static void -padlock_sha_init(struct padlock_sha_ctx *ctx) +padlock_sha_init(void *vctx) { + struct padlock_sha_ctx *ctx; + ctx = vctx; ctx->psc_buf = NULL; ctx->psc_offset = 0; ctx->psc_size = 0; } static int -padlock_sha_update(struct padlock_sha_ctx *ctx, const uint8_t *buf, uint16_t bufsize) +padlock_sha_update(void *vctx, const void *buf, u_int bufsize) { + struct padlock_sha_ctx *ctx; + ctx = vctx; if (ctx->psc_size - ctx->psc_offset < bufsize) { ctx->psc_size = MAX(ctx->psc_size * 2, ctx->psc_size + bufsize); ctx->psc_buf = realloc(ctx->psc_buf, ctx->psc_size, M_PADLOCK, M_NOWAIT); if(ctx->psc_buf == NULL) return (ENOMEM); } bcopy(buf, ctx->psc_buf + ctx->psc_offset, bufsize); ctx->psc_offset += bufsize; return (0); } static void -padlock_sha_free(struct padlock_sha_ctx *ctx) +padlock_sha_free(void *vctx) { + struct padlock_sha_ctx *ctx; + ctx = vctx; if (ctx->psc_buf != NULL) { //bzero(ctx->psc_buf, ctx->psc_size); free(ctx->psc_buf, M_PADLOCK); ctx->psc_buf = NULL; ctx->psc_offset = 0; ctx->psc_size = 0; } } static void -padlock_sha1_final(uint8_t *hash, struct padlock_sha_ctx *ctx) +padlock_sha1_final(uint8_t *hash, void *vctx) { + struct padlock_sha_ctx *ctx; + ctx = vctx; padlock_do_sha1(ctx->psc_buf, hash, ctx->psc_offset); padlock_sha_free(ctx); } static void -padlock_sha256_final(uint8_t *hash, struct padlock_sha_ctx *ctx) +padlock_sha256_final(uint8_t *hash, void *vctx) { + struct padlock_sha_ctx *ctx; + ctx = vctx; padlock_do_sha256(ctx->psc_buf, hash, ctx->psc_offset); padlock_sha_free(ctx); } static void padlock_copy_ctx(struct auth_hash *axf, void *sctx, void *dctx) { if ((via_feature_xcrypt & VIA_HAS_SHA) != 0 && (axf->type == CRYPTO_SHA1_HMAC || axf->type == CRYPTO_SHA2_256_HMAC)) { struct padlock_sha_ctx *spctx = sctx, *dpctx = dctx; dpctx->psc_offset = spctx->psc_offset; dpctx->psc_size = spctx->psc_size; dpctx->psc_buf = malloc(dpctx->psc_size, M_PADLOCK, M_WAITOK); bcopy(spctx->psc_buf, dpctx->psc_buf, dpctx->psc_size); } else { bcopy(sctx, dctx, axf->ctxsize); } } static void padlock_free_ctx(struct auth_hash *axf, void *ctx) { if ((via_feature_xcrypt & VIA_HAS_SHA) != 0 && (axf->type == CRYPTO_SHA1_HMAC || axf->type == CRYPTO_SHA2_256_HMAC)) { padlock_sha_free(ctx); } } static void padlock_hash_key_setup(struct padlock_session *ses, const uint8_t *key, int klen) { struct auth_hash *axf; axf = ses->ses_axf; /* * Try to free contexts before using them, because * padlock_hash_key_setup() can be called twice - once from * padlock_newsession() and again from padlock_process(). */ padlock_free_ctx(axf, ses->ses_ictx); padlock_free_ctx(axf, ses->ses_octx); hmac_init_ipad(axf, key, klen, ses->ses_ictx); hmac_init_opad(axf, key, klen, ses->ses_octx); } /* * Compute keyed-hash authenticator. */ static int padlock_authcompute(struct padlock_session *ses, struct cryptop *crp) { u_char hash[HASH_MAX_LEN], hash2[HASH_MAX_LEN]; struct auth_hash *axf; union authctx ctx; int error; axf = ses->ses_axf; padlock_copy_ctx(axf, ses->ses_ictx, &ctx); error = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, - (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); + axf->Update, &ctx); if (error != 0) { padlock_free_ctx(axf, &ctx); return (error); } error = crypto_apply(crp, crp->crp_payload_start, - crp->crp_payload_length, - (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); + crp->crp_payload_length, axf->Update, &ctx); if (error != 0) { padlock_free_ctx(axf, &ctx); return (error); } axf->Final(hash, &ctx); padlock_copy_ctx(axf, ses->ses_octx, &ctx); axf->Update(&ctx, hash, axf->hashsize); axf->Final(hash, &ctx); if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { crypto_copydata(crp, crp->crp_digest_start, ses->ses_mlen, hash2); if (timingsafe_bcmp(hash, hash2, ses->ses_mlen) != 0) return (EBADMSG); } else crypto_copyback(crp, crp->crp_digest_start, ses->ses_mlen, hash); return (0); } /* Find software structure which describes HMAC algorithm. */ static struct auth_hash * padlock_hash_lookup(int alg) { struct auth_hash *axf; switch (alg) { case CRYPTO_NULL_HMAC: axf = &auth_hash_null; break; case CRYPTO_SHA1_HMAC: if ((via_feature_xcrypt & VIA_HAS_SHA) != 0) axf = &padlock_hmac_sha1; else axf = &auth_hash_hmac_sha1; break; case CRYPTO_RIPEMD160_HMAC: axf = &auth_hash_hmac_ripemd_160; break; case CRYPTO_SHA2_256_HMAC: if ((via_feature_xcrypt & VIA_HAS_SHA) != 0) axf = &padlock_hmac_sha256; else axf = &auth_hash_hmac_sha2_256; break; case CRYPTO_SHA2_384_HMAC: axf = &auth_hash_hmac_sha2_384; break; case CRYPTO_SHA2_512_HMAC: axf = &auth_hash_hmac_sha2_512; break; default: axf = NULL; break; } return (axf); } bool padlock_hash_check(const struct crypto_session_params *csp) { return (padlock_hash_lookup(csp->csp_auth_alg) != NULL); } int padlock_hash_setup(struct padlock_session *ses, const struct crypto_session_params *csp) { ses->ses_axf = padlock_hash_lookup(csp->csp_auth_alg); if (csp->csp_auth_mlen == 0) ses->ses_mlen = ses->ses_axf->hashsize; else ses->ses_mlen = csp->csp_auth_mlen; /* Allocate memory for HMAC inner and outer contexts. */ ses->ses_ictx = malloc(ses->ses_axf->ctxsize, M_PADLOCK, M_ZERO | M_NOWAIT); ses->ses_octx = malloc(ses->ses_axf->ctxsize, M_PADLOCK, M_ZERO | M_NOWAIT); if (ses->ses_ictx == NULL || ses->ses_octx == NULL) return (ENOMEM); /* Setup key if given. */ if (csp->csp_auth_key != NULL) { padlock_hash_key_setup(ses, csp->csp_auth_key, csp->csp_auth_klen); } return (0); } int padlock_hash_process(struct padlock_session *ses, struct cryptop *crp, const struct crypto_session_params *csp) { struct thread *td; int error; td = curthread; fpu_kern_enter(td, ses->ses_fpu_ctx, FPU_KERN_NORMAL | FPU_KERN_KTHR); if (crp->crp_auth_key != NULL) padlock_hash_key_setup(ses, crp->crp_auth_key, csp->csp_auth_klen); error = padlock_authcompute(ses, crp); fpu_kern_leave(td, ses->ses_fpu_ctx); return (error); } void padlock_hash_free(struct padlock_session *ses) { if (ses->ses_ictx != NULL) { padlock_free_ctx(ses->ses_axf, ses->ses_ictx); bzero(ses->ses_ictx, ses->ses_axf->ctxsize); free(ses->ses_ictx, M_PADLOCK); ses->ses_ictx = NULL; } if (ses->ses_octx != NULL) { padlock_free_ctx(ses->ses_axf, ses->ses_octx); bzero(ses->ses_octx, ses->ses_axf->ctxsize); free(ses->ses_octx, M_PADLOCK); ses->ses_octx = NULL; } } Index: head/sys/dev/glxsb/glxsb_hash.c =================================================================== --- head/sys/dev/glxsb/glxsb_hash.c (revision 362027) +++ head/sys/dev/glxsb/glxsb_hash.c (revision 362028) @@ -1,158 +1,157 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2006 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include "glxsb.h" /* * Implementation notes. * * The Geode LX Security Block provides AES-128-CBC acceleration. * We implement all HMAC algorithms provided by crypto(9) framework so glxsb can work * with ipsec(4) * * This code was stolen from crypto/via/padlock_hash.c */ MALLOC_DECLARE(M_GLXSB); static void glxsb_hash_key_setup(struct glxsb_session *ses, const char *key, int klen) { struct auth_hash *axf; axf = ses->ses_axf; hmac_init_ipad(axf, key, klen, ses->ses_ictx); hmac_init_opad(axf, key, klen, ses->ses_octx); } /* * Compute keyed-hash authenticator. */ static int glxsb_authcompute(struct glxsb_session *ses, struct cryptop *crp) { u_char hash[HASH_MAX_LEN], hash2[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(crp, crp->crp_aad_start, crp->crp_aad_length, - (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); + axf->Update, &ctx); if (error != 0) return (error); error = crypto_apply(crp, crp->crp_payload_start, - crp->crp_payload_length, - (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); + crp->crp_payload_length, axf->Update, &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); /* Verify or inject the authentication data */ if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { crypto_copydata(crp, crp->crp_digest_start, ses->ses_mlen, hash2); if (timingsafe_bcmp(hash, hash2, ses->ses_mlen) != 0) return (EBADMSG); } else crypto_copyback(crp, crp->crp_digest_start, ses->ses_mlen, hash); return (0); } int glxsb_hash_setup(struct glxsb_session *ses, const struct crypto_session_params *csp) { ses->ses_axf = crypto_auth_hash(csp); if (csp->csp_auth_mlen == 0) ses->ses_mlen = ses->ses_axf->hashsize; else ses->ses_mlen = csp->csp_auth_mlen; /* Allocate memory for HMAC inner and outer contexts. */ ses->ses_ictx = malloc(ses->ses_axf->ctxsize, M_GLXSB, M_ZERO | M_NOWAIT); ses->ses_octx = malloc(ses->ses_axf->ctxsize, M_GLXSB, M_ZERO | M_NOWAIT); if (ses->ses_ictx == NULL || ses->ses_octx == NULL) return (ENOMEM); /* Setup key if given. */ if (csp->csp_auth_key != NULL) { glxsb_hash_key_setup(ses, csp->csp_auth_key, csp->csp_auth_klen); } return (0); } int glxsb_hash_process(struct glxsb_session *ses, const struct crypto_session_params *csp, struct cryptop *crp) { int error; if (crp->crp_auth_key != NULL) glxsb_hash_key_setup(ses, crp->crp_auth_key, csp->csp_auth_klen); error = glxsb_authcompute(ses, crp); return (error); } void glxsb_hash_free(struct glxsb_session *ses) { if (ses->ses_ictx != NULL) { bzero(ses->ses_ictx, ses->ses_axf->ctxsize); free(ses->ses_ictx, M_GLXSB); ses->ses_ictx = NULL; } if (ses->ses_octx != NULL) { bzero(ses->ses_octx, ses->ses_axf->ctxsize); free(ses->ses_octx, M_GLXSB); ses->ses_octx = NULL; } } Index: head/sys/opencrypto/cbc_mac.c =================================================================== --- head/sys/opencrypto/cbc_mac.c (revision 362027) +++ head/sys/opencrypto/cbc_mac.c (revision 362028) @@ -1,265 +1,279 @@ /* * Copyright (c) 2018-2019 iXsystems Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include /* * Given two CCM_CBC_BLOCK_LEN blocks, xor * them into dst, and then encrypt dst. */ static void xor_and_encrypt(struct aes_cbc_mac_ctx *ctx, const uint8_t *src, uint8_t *dst) { const uint64_t *b1; uint64_t *b2; uint64_t temp_block[CCM_CBC_BLOCK_LEN/sizeof(uint64_t)]; b1 = (const uint64_t*)src; b2 = (uint64_t*)dst; for (size_t count = 0; count < CCM_CBC_BLOCK_LEN/sizeof(uint64_t); count++) { temp_block[count] = b1[count] ^ b2[count]; } rijndaelEncrypt(ctx->keysched, ctx->rounds, (void*)temp_block, dst); } void -AES_CBC_MAC_Init(struct aes_cbc_mac_ctx *ctx) +AES_CBC_MAC_Init(void *vctx) { + struct aes_cbc_mac_ctx *ctx; + + ctx = vctx; bzero(ctx, sizeof(*ctx)); } void -AES_CBC_MAC_Setkey(struct aes_cbc_mac_ctx *ctx, const uint8_t *key, uint16_t klen) +AES_CBC_MAC_Setkey(void *vctx, const uint8_t *key, u_int klen) { + struct aes_cbc_mac_ctx *ctx; + + ctx = vctx; ctx->rounds = rijndaelKeySetupEnc(ctx->keysched, key, klen * 8); } /* * This is called to set the nonce, aka IV. * Before this call, the authDataLength and cryptDataLength fields * MUST have been set. Sadly, there's no way to return an error. * * The CBC-MAC algorithm requires that the first block contain the * nonce, as well as information about the sizes and lengths involved. */ void -AES_CBC_MAC_Reinit(struct aes_cbc_mac_ctx *ctx, const uint8_t *nonce, uint16_t nonceLen) +AES_CBC_MAC_Reinit(void *vctx, const uint8_t *nonce, u_int nonceLen) { + struct aes_cbc_mac_ctx *ctx = vctx; uint8_t b0[CCM_CBC_BLOCK_LEN]; uint8_t *bp = b0, flags = 0; uint8_t L = 0; uint64_t dataLength = ctx->cryptDataLength; KASSERT(nonceLen >= 7 && nonceLen <= 13, ("nonceLen must be between 7 and 13 bytes")); ctx->nonce = nonce; ctx->nonceLength = nonceLen; ctx->authDataCount = 0; ctx->blockIndex = 0; explicit_bzero(ctx->staging_block, sizeof(ctx->staging_block)); /* * Need to determine the L field value. This is the number of * bytes needed to specify the length of the message; the length * is whatever is left in the 16 bytes after specifying flags and * the nonce. */ L = 15 - nonceLen; flags = ((ctx->authDataLength > 0) << 6) + (((AES_CBC_MAC_HASH_LEN - 2) / 2) << 3) + L - 1; /* * Now we need to set up the first block, which has flags, nonce, * and the message length. */ b0[0] = flags; bcopy(nonce, b0 + 1, nonceLen); bp = b0 + 1 + nonceLen; /* Need to copy L' [aka L-1] bytes of cryptDataLength */ for (uint8_t *dst = b0 + sizeof(b0) - 1; dst >= bp; dst--) { *dst = dataLength; dataLength >>= 8; } /* Now need to encrypt b0 */ rijndaelEncrypt(ctx->keysched, ctx->rounds, b0, ctx->block); /* If there is auth data, we need to set up the staging block */ if (ctx->authDataLength) { size_t addLength; if (ctx->authDataLength < ((1<<16) - (1<<8))) { uint16_t sizeVal = htobe16(ctx->authDataLength); bcopy(&sizeVal, ctx->staging_block, sizeof(sizeVal)); addLength = sizeof(sizeVal); } else if (ctx->authDataLength < (1ULL<<32)) { uint32_t sizeVal = htobe32(ctx->authDataLength); ctx->staging_block[0] = 0xff; ctx->staging_block[1] = 0xfe; bcopy(&sizeVal, ctx->staging_block+2, sizeof(sizeVal)); addLength = 2 + sizeof(sizeVal); } else { uint64_t sizeVal = htobe64(ctx->authDataLength); ctx->staging_block[0] = 0xff; ctx->staging_block[1] = 0xff; bcopy(&sizeVal, ctx->staging_block+2, sizeof(sizeVal)); addLength = 2 + sizeof(sizeVal); } ctx->blockIndex = addLength; /* * The length descriptor goes into the AAD buffer, so we * need to account for it. */ ctx->authDataLength += addLength; ctx->authDataCount = addLength; } } int -AES_CBC_MAC_Update(struct aes_cbc_mac_ctx *ctx, const uint8_t *data, - uint16_t length) +AES_CBC_MAC_Update(void *vctx, const void *vdata, u_int length) { + struct aes_cbc_mac_ctx *ctx; + const uint8_t *data; size_t copy_amt; + ctx = vctx; + data = vdata; + /* * This will be called in one of two phases: * (1) Applying authentication data, or * (2) Applying the payload data. * * Because CBC-MAC puts the authentication data size before the * data, subsequent calls won't be block-size-aligned. Which * complicates things a fair bit. * * The payload data doesn't have that problem. */ if (ctx->authDataCount < ctx->authDataLength) { /* * We need to process data as authentication data. * Since we may be out of sync, we may also need * to pad out the staging block. */ const uint8_t *ptr = data; while (length > 0) { copy_amt = MIN(length, sizeof(ctx->staging_block) - ctx->blockIndex); bcopy(ptr, ctx->staging_block + ctx->blockIndex, copy_amt); ptr += copy_amt; length -= copy_amt; ctx->authDataCount += copy_amt; ctx->blockIndex += copy_amt; ctx->blockIndex %= sizeof(ctx->staging_block); if (ctx->blockIndex == 0 || ctx->authDataCount == ctx->authDataLength) { /* * We're done with this block, so we * xor staging_block with block, and then * encrypt it. */ xor_and_encrypt(ctx, ctx->staging_block, ctx->block); bzero(ctx->staging_block, sizeof(ctx->staging_block)); ctx->blockIndex = 0; if (ctx->authDataCount >= ctx->authDataLength) break; } } /* * We'd like to be able to check length == 0 and return * here, but the way OCF calls us, length is always * blksize (16, in this case). So we have to count on * the fact that OCF calls us separately for the AAD and * for the real data. */ return (0); } /* * If we're here, then we're encoding payload data. * This is marginally easier, except that _Update can * be called with non-aligned update lengths. As a result, * we still need to use the staging block. */ KASSERT((length + ctx->cryptDataCount) <= ctx->cryptDataLength, ("More encryption data than allowed")); while (length) { uint8_t *ptr; copy_amt = MIN(sizeof(ctx->staging_block) - ctx->blockIndex, length); ptr = ctx->staging_block + ctx->blockIndex; bcopy(data, ptr, copy_amt); data += copy_amt; ctx->blockIndex += copy_amt; ctx->cryptDataCount += copy_amt; length -= copy_amt; if (ctx->blockIndex == sizeof(ctx->staging_block)) { /* We've got a full block */ xor_and_encrypt(ctx, ctx->staging_block, ctx->block); ctx->blockIndex = 0; bzero(ctx->staging_block, sizeof(ctx->staging_block)); } } return (0); } void -AES_CBC_MAC_Final(uint8_t *buf, struct aes_cbc_mac_ctx *ctx) +AES_CBC_MAC_Final(uint8_t *buf, void *vctx) { + struct aes_cbc_mac_ctx *ctx; uint8_t s0[CCM_CBC_BLOCK_LEN]; - + + ctx = vctx; + /* * We first need to check to see if we've got any data * left over to encrypt. */ if (ctx->blockIndex != 0) { xor_and_encrypt(ctx, ctx->staging_block, ctx->block); ctx->cryptDataCount += ctx->blockIndex; ctx->blockIndex = 0; explicit_bzero(ctx->staging_block, sizeof(ctx->staging_block)); } bzero(s0, sizeof(s0)); s0[0] = (15 - ctx->nonceLength) - 1; bcopy(ctx->nonce, s0 + 1, ctx->nonceLength); rijndaelEncrypt(ctx->keysched, ctx->rounds, s0, s0); for (size_t indx = 0; indx < AES_CBC_MAC_HASH_LEN; indx++) buf[indx] = ctx->block[indx] ^ s0[indx]; explicit_bzero(s0, sizeof(s0)); } Index: head/sys/opencrypto/cbc_mac.h =================================================================== --- head/sys/opencrypto/cbc_mac.h (revision 362027) +++ head/sys/opencrypto/cbc_mac.h (revision 362028) @@ -1,67 +1,67 @@ /* * Copyright (c) 2014 The FreeBSD Foundation * Copyright (c) 2018, iXsystems Inc. * All rights reserved. * * This software was developed by Sean Eric Fagan, with lots of references * to existing AES-CCM (gmac) code. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * */ #ifndef _CBC_CCM_H # define _CBC_CCM_H # include # include # define CCM_CBC_BLOCK_LEN 16 /* 128 bits */ # define CCM_CBC_MAX_DIGEST_LEN 16 # define CCM_CBC_MIN_DIGEST_LEN 4 /* * This is the authentication context structure; * the encryption one is similar. */ struct aes_cbc_mac_ctx { uint64_t authDataLength, authDataCount; uint64_t cryptDataLength, cryptDataCount; int blockIndex; uint8_t staging_block[CCM_CBC_BLOCK_LEN]; uint8_t block[CCM_CBC_BLOCK_LEN]; const uint8_t *nonce; int nonceLength; /* This one is in bytes, not bits! */ /* AES state data */ int rounds; uint32_t keysched[4*(RIJNDAEL_MAXNR+1)]; }; -void AES_CBC_MAC_Init(struct aes_cbc_mac_ctx *); -void AES_CBC_MAC_Setkey(struct aes_cbc_mac_ctx *, const uint8_t *, uint16_t); -void AES_CBC_MAC_Reinit(struct aes_cbc_mac_ctx *, const uint8_t *, uint16_t); -int AES_CBC_MAC_Update(struct aes_cbc_mac_ctx *, const uint8_t *, uint16_t); -void AES_CBC_MAC_Final(uint8_t *, struct aes_cbc_mac_ctx *); +void AES_CBC_MAC_Init(void *); +void AES_CBC_MAC_Setkey(void *, const uint8_t *, u_int); +void AES_CBC_MAC_Reinit(void *, const uint8_t *, u_int); +int AES_CBC_MAC_Update(void *, const void *, u_int); +void AES_CBC_MAC_Final(uint8_t *, void *); #endif /* _CBC_CCM_H */ Index: head/sys/opencrypto/criov.c =================================================================== --- head/sys/opencrypto/criov.c (revision 362027) +++ head/sys/opencrypto/criov.c (revision 362028) @@ -1,557 +1,558 @@ /* $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $ */ /*- * Copyright (c) 1999 Theo de Raadt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include /* * This macro is only for avoiding code duplication, as we need to skip * given number of bytes in the same way in three functions below. */ #define CUIO_SKIP() do { \ KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \ KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \ while (off > 0) { \ KASSERT(iol >= 0, ("%s: empty in skip", __func__)); \ if (off < iov->iov_len) \ break; \ off -= iov->iov_len; \ iol--; \ iov++; \ } \ } while (0) static void cuio_copydata(struct uio* uio, int off, int len, caddr_t cp) { struct iovec *iov = uio->uio_iov; int iol = uio->uio_iovcnt; unsigned count; CUIO_SKIP(); while (len > 0) { KASSERT(iol >= 0, ("%s: empty", __func__)); count = min(iov->iov_len - off, len); bcopy(((caddr_t)iov->iov_base) + off, cp, count); len -= count; cp += count; off = 0; iol--; iov++; } } static void cuio_copyback(struct uio* uio, int off, int len, c_caddr_t cp) { struct iovec *iov = uio->uio_iov; int iol = uio->uio_iovcnt; unsigned count; CUIO_SKIP(); while (len > 0) { KASSERT(iol >= 0, ("%s: empty", __func__)); count = min(iov->iov_len - off, len); bcopy(cp, ((caddr_t)iov->iov_base) + off, count); len -= count; cp += count; off = 0; iol--; iov++; } } /* * Return the index and offset of location in iovec list. */ static int cuio_getptr(struct uio *uio, int loc, int *off) { int ind, len; ind = 0; while (loc >= 0 && ind < uio->uio_iovcnt) { len = uio->uio_iov[ind].iov_len; if (len > loc) { *off = loc; return (ind); } loc -= len; ind++; } if (ind > 0 && loc == 0) { ind--; *off = uio->uio_iov[ind].iov_len; return (ind); } return (-1); } void crypto_cursor_init(struct crypto_buffer_cursor *cc, const struct crypto_buffer *cb) { memset(cc, 0, sizeof(*cc)); cc->cc_type = cb->cb_type; switch (cc->cc_type) { case CRYPTO_BUF_CONTIG: cc->cc_buf = cb->cb_buf; cc->cc_buf_len = cb->cb_buf_len; break; case CRYPTO_BUF_MBUF: cc->cc_mbuf = cb->cb_mbuf; break; case CRYPTO_BUF_UIO: cc->cc_iov = cb->cb_uio->uio_iov; break; default: #ifdef INVARIANTS panic("%s: invalid buffer type %d", __func__, cb->cb_type); #endif break; } } void crypto_cursor_advance(struct crypto_buffer_cursor *cc, size_t amount) { size_t remain; switch (cc->cc_type) { case CRYPTO_BUF_CONTIG: MPASS(cc->cc_buf_len >= amount); cc->cc_buf += amount; cc->cc_buf_len -= amount; break; case CRYPTO_BUF_MBUF: for (;;) { remain = cc->cc_mbuf->m_len - cc->cc_offset; if (amount < remain) { cc->cc_offset += amount; break; } amount -= remain; cc->cc_mbuf = cc->cc_mbuf->m_next; cc->cc_offset = 0; if (amount == 0) break; } break; case CRYPTO_BUF_UIO: for (;;) { remain = cc->cc_iov->iov_len - cc->cc_offset; if (amount < remain) { cc->cc_offset += amount; break; } amount -= remain; cc->cc_iov++; cc->cc_offset = 0; if (amount == 0) break; } break; default: #ifdef INVARIANTS panic("%s: invalid buffer type %d", __func__, cc->cc_type); #endif break; } } void * crypto_cursor_segbase(struct crypto_buffer_cursor *cc) { switch (cc->cc_type) { case CRYPTO_BUF_CONTIG: return (cc->cc_buf); case CRYPTO_BUF_MBUF: if (cc->cc_mbuf == NULL) return (NULL); KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0, ("%s: not supported for unmapped mbufs", __func__)); return (mtod(cc->cc_mbuf, char *) + cc->cc_offset); case CRYPTO_BUF_UIO: return ((char *)cc->cc_iov->iov_base + cc->cc_offset); default: #ifdef INVARIANTS panic("%s: invalid buffer type %d", __func__, cc->cc_type); #endif return (NULL); } } size_t crypto_cursor_seglen(struct crypto_buffer_cursor *cc) { switch (cc->cc_type) { case CRYPTO_BUF_CONTIG: return (cc->cc_buf_len); case CRYPTO_BUF_MBUF: if (cc->cc_mbuf == NULL) return (0); return (cc->cc_mbuf->m_len - cc->cc_offset); case CRYPTO_BUF_UIO: return (cc->cc_iov->iov_len - cc->cc_offset); default: #ifdef INVARIANTS panic("%s: invalid buffer type %d", __func__, cc->cc_type); #endif return (0); } } void crypto_cursor_copyback(struct crypto_buffer_cursor *cc, int size, const void *vsrc) { size_t remain, todo; const char *src; char *dst; src = vsrc; switch (cc->cc_type) { case CRYPTO_BUF_CONTIG: MPASS(cc->cc_buf_len >= size); memcpy(cc->cc_buf, src, size); cc->cc_buf += size; cc->cc_buf_len -= size; break; case CRYPTO_BUF_MBUF: for (;;) { KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0, ("%s: not supported for unmapped mbufs", __func__)); dst = mtod(cc->cc_mbuf, char *) + cc->cc_offset; remain = cc->cc_mbuf->m_len - cc->cc_offset; todo = MIN(remain, size); memcpy(dst, src, todo); src += todo; if (todo < remain) { cc->cc_offset += todo; break; } size -= todo; cc->cc_mbuf = cc->cc_mbuf->m_next; cc->cc_offset = 0; if (size == 0) break; } break; case CRYPTO_BUF_UIO: for (;;) { dst = (char *)cc->cc_iov->iov_base + cc->cc_offset; remain = cc->cc_iov->iov_len - cc->cc_offset; todo = MIN(remain, size); memcpy(dst, src, todo); src += todo; if (todo < remain) { cc->cc_offset += todo; break; } size -= todo; cc->cc_iov++; cc->cc_offset = 0; if (size == 0) break; } break; default: #ifdef INVARIANTS panic("%s: invalid buffer type %d", __func__, cc->cc_type); #endif break; } } void crypto_cursor_copydata(struct crypto_buffer_cursor *cc, int size, void *vdst) { size_t remain, todo; const char *src; char *dst; dst = vdst; switch (cc->cc_type) { case CRYPTO_BUF_CONTIG: MPASS(cc->cc_buf_len >= size); memcpy(dst, cc->cc_buf, size); cc->cc_buf += size; cc->cc_buf_len -= size; break; case CRYPTO_BUF_MBUF: for (;;) { KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0, ("%s: not supported for unmapped mbufs", __func__)); src = mtod(cc->cc_mbuf, const char *) + cc->cc_offset; remain = cc->cc_mbuf->m_len - cc->cc_offset; todo = MIN(remain, size); memcpy(dst, src, todo); dst += todo; if (todo < remain) { cc->cc_offset += todo; break; } size -= todo; cc->cc_mbuf = cc->cc_mbuf->m_next; cc->cc_offset = 0; if (size == 0) break; } break; case CRYPTO_BUF_UIO: for (;;) { src = (const char *)cc->cc_iov->iov_base + cc->cc_offset; remain = cc->cc_iov->iov_len - cc->cc_offset; todo = MIN(remain, size); memcpy(dst, src, todo); dst += todo; if (todo < remain) { cc->cc_offset += todo; break; } size -= todo; cc->cc_iov++; cc->cc_offset = 0; if (size == 0) break; } break; default: #ifdef INVARIANTS panic("%s: invalid buffer type %d", __func__, cc->cc_type); #endif break; } } /* * To avoid advancing 'cursor', make a local copy that gets advanced * instead. */ void crypto_cursor_copydata_noadv(struct crypto_buffer_cursor *cc, int size, void *vdst) { struct crypto_buffer_cursor copy; copy = *cc; crypto_cursor_copydata(©, size, vdst); } /* * Apply function f to the data in an iovec list starting "off" bytes from * the beginning, continuing for "len" bytes. */ static int -cuio_apply(struct uio *uio, int off, int len, int (*f)(void *, void *, u_int), - void *arg) +cuio_apply(struct uio *uio, int off, int len, + int (*f)(void *, const void *, u_int), void *arg) { struct iovec *iov = uio->uio_iov; int iol = uio->uio_iovcnt; unsigned count; int rval; CUIO_SKIP(); while (len > 0) { KASSERT(iol >= 0, ("%s: empty", __func__)); count = min(iov->iov_len - off, len); rval = (*f)(arg, ((caddr_t)iov->iov_base) + off, count); if (rval) return (rval); len -= count; off = 0; iol--; iov++; } return (0); } void crypto_copyback(struct cryptop *crp, int off, int size, const void *src) { struct crypto_buffer *cb; if (crp->crp_obuf.cb_type != CRYPTO_BUF_NONE) cb = &crp->crp_obuf; else cb = &crp->crp_buf; switch (cb->cb_type) { case CRYPTO_BUF_MBUF: m_copyback(cb->cb_mbuf, off, size, src); break; case CRYPTO_BUF_UIO: cuio_copyback(cb->cb_uio, off, size, src); break; case CRYPTO_BUF_CONTIG: MPASS(off + size <= cb->cb_buf_len); bcopy(src, cb->cb_buf + off, size); break; default: #ifdef INVARIANTS panic("invalid crp buf type %d", cb->cb_type); #endif break; } } void crypto_copydata(struct cryptop *crp, int off, int size, void *dst) { switch (crp->crp_buf.cb_type) { case CRYPTO_BUF_MBUF: m_copydata(crp->crp_buf.cb_mbuf, off, size, dst); break; case CRYPTO_BUF_UIO: cuio_copydata(crp->crp_buf.cb_uio, off, size, dst); break; case CRYPTO_BUF_CONTIG: MPASS(off + size <= crp->crp_buf.cb_buf_len); bcopy(crp->crp_buf.cb_buf + off, dst, size); break; default: #ifdef INVARIANTS panic("invalid crp buf type %d", crp->crp_buf.cb_type); #endif break; } } int crypto_apply_buf(struct crypto_buffer *cb, int off, int len, - int (*f)(void *, void *, u_int), void *arg) + int (*f)(void *, const void *, u_int), void *arg) { int error; switch (cb->cb_type) { case CRYPTO_BUF_MBUF: - error = m_apply(cb->cb_mbuf, off, len, f, arg); + error = m_apply(cb->cb_mbuf, off, len, + (int (*)(void *, void *, u_int))f, arg); break; case CRYPTO_BUF_UIO: error = cuio_apply(cb->cb_uio, off, len, f, arg); break; case CRYPTO_BUF_CONTIG: MPASS(off + len <= cb->cb_buf_len); error = (*f)(arg, cb->cb_buf + off, len); break; default: #ifdef INVARIANTS panic("invalid crypto buf type %d", cb->cb_type); #endif error = 0; break; } return (error); } int crypto_apply(struct cryptop *crp, int off, int len, - int (*f)(void *, void *, u_int), void *arg) + int (*f)(void *, const void *, u_int), void *arg) { return (crypto_apply_buf(&crp->crp_buf, off, len, f, arg)); } static inline void * m_contiguous_subsegment(struct mbuf *m, size_t skip, size_t len) { int rel_off; MPASS(skip <= INT_MAX); m = m_getptr(m, (int)skip, &rel_off); if (m == NULL) return (NULL); MPASS(rel_off >= 0); skip = rel_off; if (skip + len > m->m_len) return (NULL); return (mtod(m, char*) + skip); } static inline void * cuio_contiguous_segment(struct uio *uio, size_t skip, size_t len) { int rel_off, idx; MPASS(skip <= INT_MAX); idx = cuio_getptr(uio, (int)skip, &rel_off); if (idx < 0) return (NULL); MPASS(rel_off >= 0); skip = rel_off; if (skip + len > uio->uio_iov[idx].iov_len) return (NULL); return ((char *)uio->uio_iov[idx].iov_base + skip); } void * crypto_buffer_contiguous_subsegment(struct crypto_buffer *cb, size_t skip, size_t len) { switch (cb->cb_type) { case CRYPTO_BUF_MBUF: return (m_contiguous_subsegment(cb->cb_mbuf, skip, len)); case CRYPTO_BUF_UIO: return (cuio_contiguous_segment(cb->cb_uio, skip, len)); case CRYPTO_BUF_CONTIG: MPASS(skip + len <= cb->cb_buf_len); return (cb->cb_buf + skip); default: #ifdef INVARIANTS panic("invalid crp buf type %d", cb->cb_type); #endif return (NULL); } } void * crypto_contiguous_subsegment(struct cryptop *crp, size_t skip, size_t len) { return (crypto_buffer_contiguous_subsegment(&crp->crp_buf, skip, len)); } Index: head/sys/opencrypto/cryptodev.h =================================================================== --- head/sys/opencrypto/cryptodev.h (revision 362027) +++ head/sys/opencrypto/cryptodev.h (revision 362028) @@ -1,705 +1,705 @@ /* $FreeBSD$ */ /* $OpenBSD: cryptodev.h,v 1.31 2002/06/11 11:14:29 beck Exp $ */ /*- * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting * * This code was written by Angelos D. Keromytis in Athens, Greece, in * February 2000. Network Security Technologies Inc. (NSTI) kindly * supported the development of this code. * * Copyright (c) 2000 Angelos D. Keromytis * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all source code copies of any software which is or includes a copy or * modification of this software. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. * * Copyright (c) 2001 Theo de Raadt * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Effort sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F30602-01-2-0537. * */ #ifndef _CRYPTO_CRYPTO_H_ #define _CRYPTO_CRYPTO_H_ #include #ifdef _KERNEL #include #include #endif /* Some initial values */ #define CRYPTO_DRIVERS_INITIAL 4 /* Hash values */ #define NULL_HASH_LEN 16 #define SHA1_HASH_LEN 20 #define RIPEMD160_HASH_LEN 20 #define SHA2_224_HASH_LEN 28 #define SHA2_256_HASH_LEN 32 #define SHA2_384_HASH_LEN 48 #define SHA2_512_HASH_LEN 64 #define AES_GMAC_HASH_LEN 16 #define POLY1305_HASH_LEN 16 #define AES_CBC_MAC_HASH_LEN 16 /* Maximum hash algorithm result length */ #define HASH_MAX_LEN SHA2_512_HASH_LEN /* Keep this updated */ #define SHA1_BLOCK_LEN 64 #define RIPEMD160_BLOCK_LEN 64 #define SHA2_224_BLOCK_LEN 64 #define SHA2_256_BLOCK_LEN 64 #define SHA2_384_BLOCK_LEN 128 #define SHA2_512_BLOCK_LEN 128 /* HMAC values */ #define NULL_HMAC_BLOCK_LEN 64 /* Maximum HMAC block length */ #define HMAC_MAX_BLOCK_LEN SHA2_512_BLOCK_LEN /* Keep this updated */ #define HMAC_IPAD_VAL 0x36 #define HMAC_OPAD_VAL 0x5C /* HMAC Key Length */ #define AES_128_GMAC_KEY_LEN 16 #define AES_192_GMAC_KEY_LEN 24 #define AES_256_GMAC_KEY_LEN 32 #define AES_128_CBC_MAC_KEY_LEN 16 #define AES_192_CBC_MAC_KEY_LEN 24 #define AES_256_CBC_MAC_KEY_LEN 32 #define POLY1305_KEY_LEN 32 /* Encryption algorithm block sizes */ #define NULL_BLOCK_LEN 4 /* IPsec to maintain alignment */ #define RIJNDAEL128_BLOCK_LEN 16 #define AES_BLOCK_LEN 16 #define AES_ICM_BLOCK_LEN 1 #define CAMELLIA_BLOCK_LEN 16 #define CHACHA20_NATIVE_BLOCK_LEN 64 #define EALG_MAX_BLOCK_LEN CHACHA20_NATIVE_BLOCK_LEN /* Keep this updated */ /* IV Lengths */ #define AES_GCM_IV_LEN 12 #define AES_CCM_IV_LEN 12 #define AES_XTS_IV_LEN 8 #define AES_XTS_ALPHA 0x87 /* GF(2^128) generator polynomial */ /* Min and Max Encryption Key Sizes */ #define NULL_MIN_KEY 0 #define NULL_MAX_KEY 256 /* 2048 bits, max key */ #define RIJNDAEL_MIN_KEY 16 #define RIJNDAEL_MAX_KEY 32 #define AES_MIN_KEY RIJNDAEL_MIN_KEY #define AES_MAX_KEY RIJNDAEL_MAX_KEY #define AES_XTS_MIN_KEY (2 * AES_MIN_KEY) #define AES_XTS_MAX_KEY (2 * AES_MAX_KEY) #define CAMELLIA_MIN_KEY 16 #define CAMELLIA_MAX_KEY 32 /* Maximum hash algorithm result length */ #define AALG_MAX_RESULT_LEN 64 /* Keep this updated */ #define CRYPTO_ALGORITHM_MIN 1 #define CRYPTO_DES_CBC 1 #define CRYPTO_3DES_CBC 2 #define CRYPTO_BLF_CBC 3 #define CRYPTO_CAST_CBC 4 #define CRYPTO_SKIPJACK_CBC 5 #define CRYPTO_MD5_HMAC 6 #define CRYPTO_SHA1_HMAC 7 #define CRYPTO_RIPEMD160_HMAC 8 #define CRYPTO_MD5_KPDK 9 #define CRYPTO_SHA1_KPDK 10 #define CRYPTO_RIJNDAEL128_CBC 11 /* 128 bit blocksize */ #define CRYPTO_AES_CBC 11 /* 128 bit blocksize -- the same as above */ #define CRYPTO_ARC4 12 #define CRYPTO_MD5 13 #define CRYPTO_SHA1 14 #define CRYPTO_NULL_HMAC 15 #define CRYPTO_NULL_CBC 16 #define CRYPTO_DEFLATE_COMP 17 /* Deflate compression algorithm */ #define CRYPTO_SHA2_256_HMAC 18 #define CRYPTO_SHA2_384_HMAC 19 #define CRYPTO_SHA2_512_HMAC 20 #define CRYPTO_CAMELLIA_CBC 21 #define CRYPTO_AES_XTS 22 #define CRYPTO_AES_ICM 23 /* commonly known as CTR mode */ #define CRYPTO_AES_NIST_GMAC 24 /* GMAC only */ #define CRYPTO_AES_NIST_GCM_16 25 /* 16 byte ICV */ #ifdef _KERNEL #define CRYPTO_AES_128_NIST_GMAC 26 /* auth side */ #define CRYPTO_AES_192_NIST_GMAC 27 /* auth side */ #define CRYPTO_AES_256_NIST_GMAC 28 /* auth side */ #endif #define CRYPTO_BLAKE2B 29 /* Blake2b hash */ #define CRYPTO_BLAKE2S 30 /* Blake2s hash */ #define CRYPTO_CHACHA20 31 /* Chacha20 stream cipher */ #define CRYPTO_SHA2_224_HMAC 32 #define CRYPTO_RIPEMD160 33 #define CRYPTO_SHA2_224 34 #define CRYPTO_SHA2_256 35 #define CRYPTO_SHA2_384 36 #define CRYPTO_SHA2_512 37 #define CRYPTO_POLY1305 38 #define CRYPTO_AES_CCM_CBC_MAC 39 /* auth side */ #define CRYPTO_AES_CCM_16 40 /* cipher side */ #define CRYPTO_ALGORITHM_MAX 40 /* Keep updated - see below */ #define CRYPTO_ALGO_VALID(x) ((x) >= CRYPTO_ALGORITHM_MIN && \ (x) <= CRYPTO_ALGORITHM_MAX) /* Algorithm flags */ #define CRYPTO_ALG_FLAG_SUPPORTED 0x01 /* Algorithm is supported */ #define CRYPTO_ALG_FLAG_RNG_ENABLE 0x02 /* Has HW RNG for DH/DSA */ #define CRYPTO_ALG_FLAG_DSA_SHA 0x04 /* Can do SHA on msg */ /* * Crypto driver/device flags. They can set in the crid * parameter when creating a session or submitting a key * op to affect the device/driver assigned. If neither * of these are specified then the crid is assumed to hold * the driver id of an existing (and suitable) device that * must be used to satisfy the request. */ #define CRYPTO_FLAG_HARDWARE 0x01000000 /* hardware accelerated */ #define CRYPTO_FLAG_SOFTWARE 0x02000000 /* software implementation */ /* NB: deprecated */ struct session_op { u_int32_t cipher; /* ie. CRYPTO_AES_CBC */ u_int32_t mac; /* ie. CRYPTO_SHA2_256_HMAC */ u_int32_t keylen; /* cipher key */ c_caddr_t key; int mackeylen; /* mac key */ c_caddr_t mackey; u_int32_t ses; /* returns: session # */ }; /* * session and crypt _op structs are used by userspace programs to interact * with /dev/crypto. Confusingly, the internal kernel interface is named * "cryptop" (no underscore). */ struct session2_op { u_int32_t cipher; /* ie. CRYPTO_AES_CBC */ u_int32_t mac; /* ie. CRYPTO_SHA2_256_HMAC */ u_int32_t keylen; /* cipher key */ c_caddr_t key; int mackeylen; /* mac key */ c_caddr_t mackey; u_int32_t ses; /* returns: session # */ int crid; /* driver id + flags (rw) */ int pad[4]; /* for future expansion */ }; struct crypt_op { u_int32_t ses; u_int16_t op; /* i.e. COP_ENCRYPT */ #define COP_ENCRYPT 1 #define COP_DECRYPT 2 u_int16_t flags; #define COP_F_CIPHER_FIRST 0x0001 /* Cipher before MAC. */ #define COP_F_BATCH 0x0008 /* Batch op if possible */ u_int len; c_caddr_t src; /* become iov[] inside kernel */ caddr_t dst; caddr_t mac; /* must be big enough for chosen MAC */ c_caddr_t iv; }; /* op and flags the same as crypt_op */ struct crypt_aead { u_int32_t ses; u_int16_t op; /* i.e. COP_ENCRYPT */ u_int16_t flags; u_int len; u_int aadlen; u_int ivlen; c_caddr_t src; /* become iov[] inside kernel */ caddr_t dst; c_caddr_t aad; /* additional authenticated data */ caddr_t tag; /* must fit for chosen TAG length */ c_caddr_t iv; }; /* * Parameters for looking up a crypto driver/device by * device name or by id. The latter are returned for * created sessions (crid) and completed key operations. */ struct crypt_find_op { int crid; /* driver id + flags */ char name[32]; /* device/driver name */ }; /* bignum parameter, in packed bytes, ... */ struct crparam { caddr_t crp_p; u_int crp_nbits; }; #define CRK_MAXPARAM 8 struct crypt_kop { u_int crk_op; /* ie. CRK_MOD_EXP or other */ u_int crk_status; /* return status */ u_short crk_iparams; /* # of input parameters */ u_short crk_oparams; /* # of output parameters */ u_int crk_crid; /* NB: only used by CIOCKEY2 (rw) */ struct crparam crk_param[CRK_MAXPARAM]; }; #define CRK_ALGORITM_MIN 0 #define CRK_MOD_EXP 0 #define CRK_MOD_EXP_CRT 1 #define CRK_DSA_SIGN 2 #define CRK_DSA_VERIFY 3 #define CRK_DH_COMPUTE_KEY 4 #define CRK_ALGORITHM_MAX 4 /* Keep updated - see below */ #define CRF_MOD_EXP (1 << CRK_MOD_EXP) #define CRF_MOD_EXP_CRT (1 << CRK_MOD_EXP_CRT) #define CRF_DSA_SIGN (1 << CRK_DSA_SIGN) #define CRF_DSA_VERIFY (1 << CRK_DSA_VERIFY) #define CRF_DH_COMPUTE_KEY (1 << CRK_DH_COMPUTE_KEY) /* * done against open of /dev/crypto, to get a cloned descriptor. * Please use F_SETFD against the cloned descriptor. */ #define CRIOGET _IOWR('c', 100, u_int32_t) #define CRIOASYMFEAT CIOCASYMFEAT #define CRIOFINDDEV CIOCFINDDEV /* the following are done against the cloned descriptor */ #define CIOCGSESSION _IOWR('c', 101, struct session_op) #define CIOCFSESSION _IOW('c', 102, u_int32_t) #define CIOCCRYPT _IOWR('c', 103, struct crypt_op) #define CIOCKEY _IOWR('c', 104, struct crypt_kop) #define CIOCASYMFEAT _IOR('c', 105, u_int32_t) #define CIOCGSESSION2 _IOWR('c', 106, struct session2_op) #define CIOCKEY2 _IOWR('c', 107, struct crypt_kop) #define CIOCFINDDEV _IOWR('c', 108, struct crypt_find_op) #define CIOCCRYPTAEAD _IOWR('c', 109, struct crypt_aead) struct cryptotstat { struct timespec acc; /* total accumulated time */ struct timespec min; /* min time */ struct timespec max; /* max time */ u_int32_t count; /* number of observations */ }; struct cryptostats { u_int32_t cs_ops; /* symmetric crypto ops submitted */ u_int32_t cs_errs; /* symmetric crypto ops that failed */ u_int32_t cs_kops; /* asymetric/key ops submitted */ u_int32_t cs_kerrs; /* asymetric/key ops that failed */ u_int32_t cs_intrs; /* crypto swi thread activations */ u_int32_t cs_rets; /* crypto return thread activations */ u_int32_t cs_blocks; /* symmetric op driver block */ u_int32_t cs_kblocks; /* symmetric op driver block */ /* * When CRYPTO_TIMING is defined at compile time and the * sysctl debug.crypto is set to 1, the crypto system will * accumulate statistics about how long it takes to process * crypto requests at various points during processing. */ struct cryptotstat cs_invoke; /* crypto_dipsatch -> crypto_invoke */ struct cryptotstat cs_done; /* crypto_invoke -> crypto_done */ struct cryptotstat cs_cb; /* crypto_done -> callback */ struct cryptotstat cs_finis; /* callback -> callback return */ }; #ifdef _KERNEL /* * Return values for cryptodev_probesession methods. */ #define CRYPTODEV_PROBE_HARDWARE (-100) #define CRYPTODEV_PROBE_ACCEL_SOFTWARE (-200) #define CRYPTODEV_PROBE_SOFTWARE (-500) #if 0 #define CRYPTDEB(s, ...) do { \ printf("%s:%d: " s "\n", __FILE__, __LINE__, ## __VA_ARGS__); \ } while (0) #else #define CRYPTDEB(...) do { } while (0) #endif struct crypto_session_params { int csp_mode; /* Type of operations to perform. */ #define CSP_MODE_NONE 0 #define CSP_MODE_COMPRESS 1 /* Compression/decompression. */ #define CSP_MODE_CIPHER 2 /* Encrypt/decrypt. */ #define CSP_MODE_DIGEST 3 /* Compute/verify digest. */ #define CSP_MODE_AEAD 4 /* Combined auth/encryption. */ #define CSP_MODE_ETA 5 /* IPsec style encrypt-then-auth */ int csp_flags; #define CSP_F_SEPARATE_OUTPUT 0x0001 /* Requests can use separate output */ int csp_ivlen; /* IV length in bytes. */ int csp_cipher_alg; int csp_cipher_klen; /* Key length in bytes. */ const void *csp_cipher_key; int csp_auth_alg; int csp_auth_klen; /* Key length in bytes. */ const void *csp_auth_key; int csp_auth_mlen; /* Number of digest bytes to use. 0 means all. */ }; enum crypto_buffer_type { CRYPTO_BUF_NONE = 0, CRYPTO_BUF_CONTIG, CRYPTO_BUF_UIO, CRYPTO_BUF_MBUF, CRYPTO_BUF_LAST = CRYPTO_BUF_MBUF }; /* * Description of a data buffer for a request. Requests can either * have a single buffer that is modified in place or separate input * and output buffers. */ struct crypto_buffer { union { struct { char *cb_buf; int cb_buf_len; }; struct mbuf *cb_mbuf; struct uio *cb_uio; }; enum crypto_buffer_type cb_type; }; /* * A cursor is used to iterate through a crypto request data buffer. */ struct crypto_buffer_cursor { union { char *cc_buf; struct mbuf *cc_mbuf; struct iovec *cc_iov; }; union { int cc_buf_len; size_t cc_offset; }; enum crypto_buffer_type cc_type; }; /* Structure describing complete operation */ struct cryptop { TAILQ_ENTRY(cryptop) crp_next; struct task crp_task; crypto_session_t crp_session; /* Session */ int crp_olen; /* Result total length */ int crp_etype; /* * Error type (zero means no error). * All error codes except EAGAIN * indicate possible data corruption (as in, * the data have been touched). On all * errors, the crp_session may have changed * (reset to a new one), so the caller * should always check and use the new * value on future requests. */ int crp_flags; #define CRYPTO_F_BATCH 0x0008 /* Batch op if possible */ #define CRYPTO_F_CBIMM 0x0010 /* Do callback immediately */ #define CRYPTO_F_DONE 0x0020 /* Operation completed */ #define CRYPTO_F_CBIFSYNC 0x0040 /* Do CBIMM if op is synchronous */ #define CRYPTO_F_ASYNC 0x0080 /* Dispatch crypto jobs on several threads * if op is synchronous */ #define CRYPTO_F_ASYNC_KEEPORDER 0x0100 /* * Dispatch the crypto jobs in the same * order there are submitted. Applied only * if CRYPTO_F_ASYNC flags is set */ #define CRYPTO_F_IV_SEPARATE 0x0200 /* Use crp_iv[] as IV. */ int crp_op; struct crypto_buffer crp_buf; struct crypto_buffer crp_obuf; int crp_aad_start; /* Location of AAD. */ int crp_aad_length; /* 0 => no AAD. */ int crp_iv_start; /* Location of IV. IV length is from * the session. */ int crp_payload_start; /* Location of ciphertext. */ int crp_payload_output_start; int crp_payload_length; int crp_digest_start; /* Location of MAC/tag. Length is * from the session. */ uint8_t crp_iv[EALG_MAX_BLOCK_LEN]; /* IV if IV_SEPARATE. */ const void *crp_cipher_key; /* New cipher key if non-NULL. */ const void *crp_auth_key; /* New auth key if non-NULL. */ void *crp_opaque; /* Opaque pointer, passed along */ int (*crp_callback)(struct cryptop *); /* Callback function */ struct bintime crp_tstamp; /* performance time stamp */ uint32_t crp_seq; /* used for ordered dispatch */ uint32_t crp_retw_id; /* * the return worker to be used, * used for ordered dispatch */ }; static __inline void _crypto_use_buf(struct crypto_buffer *cb, void *buf, int len) { cb->cb_buf = buf; cb->cb_buf_len = len; cb->cb_type = CRYPTO_BUF_CONTIG; } static __inline void _crypto_use_mbuf(struct crypto_buffer *cb, struct mbuf *m) { cb->cb_mbuf = m; cb->cb_type = CRYPTO_BUF_MBUF; } static __inline void _crypto_use_uio(struct crypto_buffer *cb, struct uio *uio) { cb->cb_uio = uio; cb->cb_type = CRYPTO_BUF_UIO; } static __inline void crypto_use_buf(struct cryptop *crp, void *buf, int len) { _crypto_use_buf(&crp->crp_buf, buf, len); } static __inline void crypto_use_mbuf(struct cryptop *crp, struct mbuf *m) { _crypto_use_mbuf(&crp->crp_buf, m); } static __inline void crypto_use_uio(struct cryptop *crp, struct uio *uio) { _crypto_use_uio(&crp->crp_buf, uio); } static __inline void crypto_use_output_buf(struct cryptop *crp, void *buf, int len) { _crypto_use_buf(&crp->crp_obuf, buf, len); } static __inline void crypto_use_output_mbuf(struct cryptop *crp, struct mbuf *m) { _crypto_use_mbuf(&crp->crp_obuf, m); } static __inline void crypto_use_output_uio(struct cryptop *crp, struct uio *uio) { _crypto_use_uio(&crp->crp_obuf, uio); } #define CRYPTOP_ASYNC(crp) \ (((crp)->crp_flags & CRYPTO_F_ASYNC) && \ crypto_ses2caps((crp)->crp_session) & CRYPTOCAP_F_SYNC) #define CRYPTOP_ASYNC_KEEPORDER(crp) \ (CRYPTOP_ASYNC(crp) && \ (crp)->crp_flags & CRYPTO_F_ASYNC_KEEPORDER) #define CRYPTO_HAS_OUTPUT_BUFFER(crp) \ ((crp)->crp_obuf.cb_type != CRYPTO_BUF_NONE) /* Flags in crp_op. */ #define CRYPTO_OP_DECRYPT 0x0 #define CRYPTO_OP_ENCRYPT 0x1 #define CRYPTO_OP_IS_ENCRYPT(op) ((op) & CRYPTO_OP_ENCRYPT) #define CRYPTO_OP_COMPUTE_DIGEST 0x0 #define CRYPTO_OP_VERIFY_DIGEST 0x2 #define CRYPTO_OP_DECOMPRESS CRYPTO_OP_DECRYPT #define CRYPTO_OP_COMPRESS CRYPTO_OP_ENCRYPT #define CRYPTO_OP_IS_COMPRESS(op) ((op) & CRYPTO_OP_COMPRESS) /* * Hints passed to process methods. */ #define CRYPTO_HINT_MORE 0x1 /* more ops coming shortly */ struct cryptkop { TAILQ_ENTRY(cryptkop) krp_next; u_int krp_op; /* ie. CRK_MOD_EXP or other */ u_int krp_status; /* return status */ u_short krp_iparams; /* # of input parameters */ u_short krp_oparams; /* # of output parameters */ u_int krp_crid; /* desired device, etc. */ uint32_t krp_hid; /* device used */ struct crparam krp_param[CRK_MAXPARAM]; /* kvm */ void (*krp_callback)(struct cryptkop *); struct cryptocap *krp_cap; }; uint32_t crypto_ses2hid(crypto_session_t crypto_session); uint32_t crypto_ses2caps(crypto_session_t crypto_session); void *crypto_get_driver_session(crypto_session_t crypto_session); const struct crypto_session_params *crypto_get_params( crypto_session_t crypto_session); struct auth_hash *crypto_auth_hash(const struct crypto_session_params *csp); struct enc_xform *crypto_cipher(const struct crypto_session_params *csp); MALLOC_DECLARE(M_CRYPTO_DATA); extern int crypto_newsession(crypto_session_t *cses, const struct crypto_session_params *params, int hard); extern void crypto_freesession(crypto_session_t cses); #define CRYPTOCAP_F_HARDWARE CRYPTO_FLAG_HARDWARE #define CRYPTOCAP_F_SOFTWARE CRYPTO_FLAG_SOFTWARE #define CRYPTOCAP_F_SYNC 0x04000000 /* operates synchronously */ #define CRYPTOCAP_F_ACCEL_SOFTWARE 0x08000000 extern int32_t crypto_get_driverid(device_t dev, size_t session_size, int flags); extern int crypto_find_driver(const char *); extern device_t crypto_find_device_byhid(int hid); extern int crypto_getcaps(int hid); extern int crypto_kregister(u_int32_t, int, u_int32_t); extern int crypto_unregister_all(u_int32_t driverid); extern int crypto_dispatch(struct cryptop *crp); extern int crypto_kdispatch(struct cryptkop *); #define CRYPTO_SYMQ 0x1 #define CRYPTO_ASYMQ 0x2 extern int crypto_unblock(u_int32_t, int); extern void crypto_done(struct cryptop *crp); extern void crypto_kdone(struct cryptkop *); extern int crypto_getfeat(int *); extern void crypto_freereq(struct cryptop *crp); extern struct cryptop *crypto_getreq(crypto_session_t cses, int how); extern int crypto_usercrypto; /* userland may do crypto requests */ extern int crypto_userasymcrypto; /* userland may do asym crypto reqs */ extern int crypto_devallowsoft; /* only use hardware crypto */ #ifdef SYSCTL_DECL SYSCTL_DECL(_kern_crypto); #endif /* Helper routines for drivers to initialize auth contexts for HMAC. */ struct auth_hash; void hmac_init_ipad(struct auth_hash *axf, const char *key, int klen, void *auth_ctx); void hmac_init_opad(struct auth_hash *axf, const char *key, int klen, void *auth_ctx); /* * Crypto-related utility routines used mainly by drivers. * * Similar to m_copyback/data, *_copyback copy data from the 'src' * buffer into the crypto request's data buffer while *_copydata copy * data from the crypto request's data buffer into the the 'dst' * buffer. */ void crypto_copyback(struct cryptop *crp, int off, int size, const void *src); void crypto_copydata(struct cryptop *crp, int off, int size, void *dst); int crypto_apply(struct cryptop *crp, int off, int len, - int (*f)(void *, void *, u_int), void *arg); + int (*f)(void *, const void *, u_int), void *arg); void *crypto_contiguous_subsegment(struct cryptop *crp, size_t skip, size_t len); int crypto_apply_buf(struct crypto_buffer *cb, int off, int len, - int (*f)(void *, void *, u_int), void *arg); + int (*f)(void *, const void *, u_int), void *arg); void *crypto_buffer_contiguous_subsegment(struct crypto_buffer *cb, size_t skip, size_t len); size_t crypto_buffer_len(struct crypto_buffer *cb); void crypto_cursor_init(struct crypto_buffer_cursor *cc, const struct crypto_buffer *cb); void crypto_cursor_advance(struct crypto_buffer_cursor *cc, size_t amount); void *crypto_cursor_segbase(struct crypto_buffer_cursor *cc); size_t crypto_cursor_seglen(struct crypto_buffer_cursor *cc); void crypto_cursor_copyback(struct crypto_buffer_cursor *cc, int size, const void *vsrc); void crypto_cursor_copydata(struct crypto_buffer_cursor *cc, int size, void *vdst); void crypto_cursor_copydata_noadv(struct crypto_buffer_cursor *cc, int size, void *vdst); static __inline void crypto_read_iv(struct cryptop *crp, void *iv) { const struct crypto_session_params *csp; csp = crypto_get_params(crp->crp_session); if (crp->crp_flags & CRYPTO_F_IV_SEPARATE) memcpy(iv, crp->crp_iv, csp->csp_ivlen); else crypto_copydata(crp, crp->crp_iv_start, csp->csp_ivlen, iv); } #endif /* _KERNEL */ #endif /* _CRYPTO_CRYPTO_H_ */ Index: head/sys/opencrypto/cryptosoft.c =================================================================== --- head/sys/opencrypto/cryptosoft.c (revision 362027) +++ head/sys/opencrypto/cryptosoft.c (revision 362028) @@ -1,1432 +1,1431 @@ /* $OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $ */ /*- * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting * * This code was written by Angelos D. Keromytis in Athens, Greece, in * February 2000. Network Security Technologies Inc. (NSTI) kindly * supported the development of this code. * * Copyright (c) 2000, 2001 Angelos D. Keromytis * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all source code copies of any software which is or includes a copy or * modification of this software. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cryptodev_if.h" struct swcr_auth { void *sw_ictx; void *sw_octx; struct auth_hash *sw_axf; uint16_t sw_mlen; }; struct swcr_encdec { void *sw_kschedule; struct enc_xform *sw_exf; }; struct swcr_compdec { struct comp_algo *sw_cxf; }; struct swcr_session { struct mtx swcr_lock; int (*swcr_process)(struct swcr_session *, struct cryptop *); struct swcr_auth swcr_auth; struct swcr_encdec swcr_encdec; struct swcr_compdec swcr_compdec; }; static int32_t swcr_id; static void swcr_freesession(device_t dev, crypto_session_t cses); /* Used for CRYPTO_NULL_CBC. */ static int swcr_null(struct swcr_session *ses, struct cryptop *crp) { return (0); } /* * Apply a symmetric encryption/decryption algorithm. */ static int swcr_encdec(struct swcr_session *ses, struct cryptop *crp) { unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN]; unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN]; const struct crypto_session_params *csp; struct swcr_encdec *sw; struct enc_xform *exf; int i, blks, inlen, ivlen, outlen, resid; struct crypto_buffer_cursor cc_in, cc_out; const char *inblk; char *outblk; int error; bool encrypting; error = 0; sw = &ses->swcr_encdec; exf = sw->sw_exf; ivlen = exf->ivsize; if (exf->native_blocksize == 0) { /* Check for non-padded data */ if ((crp->crp_payload_length % exf->blocksize) != 0) return (EINVAL); blks = exf->blocksize; } else blks = exf->native_blocksize; if (exf == &enc_xform_aes_icm && (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) return (EINVAL); if (crp->crp_cipher_key != NULL) { csp = crypto_get_params(crp->crp_session); error = exf->setkey(sw->sw_kschedule, crp->crp_cipher_key, csp->csp_cipher_klen); if (error) return (error); } crypto_read_iv(crp, iv); if (exf->reinit) { /* * xforms that provide a reinit method perform all IV * handling themselves. */ exf->reinit(sw->sw_kschedule, iv); } ivp = iv; crypto_cursor_init(&cc_in, &crp->crp_buf); crypto_cursor_advance(&cc_in, crp->crp_payload_start); inlen = crypto_cursor_seglen(&cc_in); inblk = crypto_cursor_segbase(&cc_in); if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { crypto_cursor_init(&cc_out, &crp->crp_obuf); crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); } else cc_out = cc_in; outlen = crypto_cursor_seglen(&cc_out); outblk = crypto_cursor_segbase(&cc_out); resid = crp->crp_payload_length; encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op); /* * Loop through encrypting blocks. 'inlen' is the remaining * length of the current segment in the input buffer. * 'outlen' is the remaining length of current segment in the * output buffer. */ while (resid >= blks) { /* * If the current block is not contained within the * current input/output segment, use 'blk' as a local * buffer. */ if (inlen < blks) { crypto_cursor_copydata(&cc_in, blks, blk); inblk = blk; } if (outlen < blks) outblk = blk; /* * Ciphers without a 'reinit' hook are assumed to be * used in CBC mode where the chaining is done here. */ if (exf->reinit != NULL) { if (encrypting) exf->encrypt(sw->sw_kschedule, inblk, outblk); else exf->decrypt(sw->sw_kschedule, inblk, outblk); } else if (encrypting) { /* XOR with previous block */ for (i = 0; i < blks; i++) outblk[i] = inblk[i] ^ ivp[i]; exf->encrypt(sw->sw_kschedule, outblk, outblk); /* * Keep encrypted block for XOR'ing * with next block */ memcpy(iv, outblk, blks); ivp = iv; } else { /* decrypt */ /* * Keep encrypted block for XOR'ing * with next block */ nivp = (ivp == iv) ? iv2 : iv; memcpy(nivp, inblk, blks); exf->decrypt(sw->sw_kschedule, inblk, outblk); /* XOR with previous block */ for (i = 0; i < blks; i++) outblk[i] ^= ivp[i]; ivp = nivp; } if (inlen < blks) { inlen = crypto_cursor_seglen(&cc_in); inblk = crypto_cursor_segbase(&cc_in); } else { crypto_cursor_advance(&cc_in, blks); inlen -= blks; inblk += blks; } if (outlen < blks) { crypto_cursor_copyback(&cc_out, blks, blk); outlen = crypto_cursor_seglen(&cc_out); outblk = crypto_cursor_segbase(&cc_out); } else { crypto_cursor_advance(&cc_out, blks); outlen -= blks; outblk += blks; } resid -= blks; } /* Handle trailing partial block for stream ciphers. */ if (resid > 0) { KASSERT(exf->native_blocksize != 0, ("%s: partial block of %d bytes for cipher %s", __func__, i, exf->name)); KASSERT(exf->reinit != NULL, ("%s: partial block cipher %s without reinit hook", __func__, exf->name)); KASSERT(resid < blks, ("%s: partial block too big", __func__)); inlen = crypto_cursor_seglen(&cc_in); outlen = crypto_cursor_seglen(&cc_out); if (inlen < resid) { crypto_cursor_copydata(&cc_in, resid, blk); inblk = blk; } else inblk = crypto_cursor_segbase(&cc_in); if (outlen < resid) outblk = blk; else outblk = crypto_cursor_segbase(&cc_out); if (encrypting) exf->encrypt_last(sw->sw_kschedule, inblk, outblk, resid); else exf->decrypt_last(sw->sw_kschedule, inblk, outblk, resid); if (outlen < resid) crypto_cursor_copyback(&cc_out, resid, blk); } explicit_bzero(blk, sizeof(blk)); explicit_bzero(iv, sizeof(iv)); explicit_bzero(iv2, sizeof(iv2)); return (0); } static void swcr_authprepare(struct auth_hash *axf, struct swcr_auth *sw, const uint8_t *key, int klen) { switch (axf->type) { case CRYPTO_SHA1_HMAC: case CRYPTO_SHA2_224_HMAC: case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: case CRYPTO_NULL_HMAC: case CRYPTO_RIPEMD160_HMAC: hmac_init_ipad(axf, key, klen, sw->sw_ictx); hmac_init_opad(axf, key, klen, sw->sw_octx); break; case CRYPTO_POLY1305: case CRYPTO_BLAKE2B: case CRYPTO_BLAKE2S: axf->Setkey(sw->sw_ictx, key, klen); axf->Init(sw->sw_ictx); break; default: panic("%s: algorithm %d doesn't use keys", __func__, axf->type); } } /* * Compute or verify hash. */ static int swcr_authcompute(struct swcr_session *ses, struct cryptop *crp) { u_char aalg[HASH_MAX_LEN]; const struct crypto_session_params *csp; struct swcr_auth *sw; struct auth_hash *axf; union authctx ctx; int err; sw = &ses->swcr_auth; axf = sw->sw_axf; if (crp->crp_auth_key != NULL) { csp = crypto_get_params(crp->crp_session); swcr_authprepare(axf, sw, crp->crp_auth_key, csp->csp_auth_klen); } bcopy(sw->sw_ictx, &ctx, axf->ctxsize); err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, - (int (*)(void *, void *, unsigned int))axf->Update, &ctx); + axf->Update, &ctx); if (err) return err; if (CRYPTO_HAS_OUTPUT_BUFFER(crp) && CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) err = crypto_apply_buf(&crp->crp_obuf, crp->crp_payload_output_start, crp->crp_payload_length, - (int (*)(void *, void *, unsigned int))axf->Update, &ctx); + axf->Update, &ctx); else err = crypto_apply(crp, crp->crp_payload_start, - crp->crp_payload_length, - (int (*)(void *, void *, unsigned int))axf->Update, &ctx); + crp->crp_payload_length, axf->Update, &ctx); if (err) return err; switch (axf->type) { case CRYPTO_SHA1: case CRYPTO_SHA2_224: case CRYPTO_SHA2_256: case CRYPTO_SHA2_384: case CRYPTO_SHA2_512: axf->Final(aalg, &ctx); break; case CRYPTO_SHA1_HMAC: case CRYPTO_SHA2_224_HMAC: case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: case CRYPTO_RIPEMD160_HMAC: if (sw->sw_octx == NULL) return EINVAL; axf->Final(aalg, &ctx); bcopy(sw->sw_octx, &ctx, axf->ctxsize); axf->Update(&ctx, aalg, axf->hashsize); axf->Final(aalg, &ctx); break; case CRYPTO_BLAKE2B: case CRYPTO_BLAKE2S: case CRYPTO_NULL_HMAC: case CRYPTO_POLY1305: axf->Final(aalg, &ctx); break; } if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { u_char uaalg[HASH_MAX_LEN]; crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, uaalg); if (timingsafe_bcmp(aalg, uaalg, sw->sw_mlen) != 0) err = EBADMSG; explicit_bzero(uaalg, sizeof(uaalg)); } else { /* Inject the authentication data */ crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, aalg); } explicit_bzero(aalg, sizeof(aalg)); return (err); } CTASSERT(INT_MAX <= (1ll<<39) - 256); /* GCM: plain text < 2^39-256 */ CTASSERT(INT_MAX <= (uint64_t)-1); /* GCM: associated data <= 2^64-1 */ static int swcr_gmac(struct swcr_session *ses, struct cryptop *crp) { uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; u_char *blk = (u_char *)blkbuf; u_char aalg[AALG_MAX_RESULT_LEN]; u_char iv[EALG_MAX_BLOCK_LEN]; struct crypto_buffer_cursor cc; union authctx ctx; struct swcr_auth *swa; struct auth_hash *axf; uint32_t *blkp; int blksz, error, ivlen, len, resid; swa = &ses->swcr_auth; axf = swa->sw_axf; bcopy(swa->sw_ictx, &ctx, axf->ctxsize); blksz = axf->blocksize; /* Initialize the IV */ ivlen = AES_GCM_IV_LEN; crypto_read_iv(crp, iv); axf->Reinit(&ctx, iv, ivlen); crypto_cursor_init(&cc, &crp->crp_buf); crypto_cursor_advance(&cc, crp->crp_payload_start); for (resid = crp->crp_payload_length; resid > 0; resid -= len) { len = MIN(resid, blksz); crypto_cursor_copydata(&cc, len, blk); bzero(blk + len, blksz - len); axf->Update(&ctx, blk, blksz); } /* length block */ bzero(blk, blksz); blkp = (uint32_t *)blk + 1; *blkp = htobe32(crp->crp_payload_length * 8); axf->Update(&ctx, blk, blksz); /* Finalize MAC */ axf->Final(aalg, &ctx); error = 0; if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { u_char uaalg[AALG_MAX_RESULT_LEN]; crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, uaalg); if (timingsafe_bcmp(aalg, uaalg, swa->sw_mlen) != 0) error = EBADMSG; explicit_bzero(uaalg, sizeof(uaalg)); } else { /* Inject the authentication data */ crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, aalg); } explicit_bzero(blkbuf, sizeof(blkbuf)); explicit_bzero(aalg, sizeof(aalg)); explicit_bzero(iv, sizeof(iv)); return (error); } static int swcr_gcm(struct swcr_session *ses, struct cryptop *crp) { uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; u_char *blk = (u_char *)blkbuf; u_char aalg[AALG_MAX_RESULT_LEN]; u_char iv[EALG_MAX_BLOCK_LEN]; struct crypto_buffer_cursor cc_in, cc_out; union authctx ctx; struct swcr_auth *swa; struct swcr_encdec *swe; struct auth_hash *axf; struct enc_xform *exf; uint32_t *blkp; int blksz, error, ivlen, len, r, resid; swa = &ses->swcr_auth; axf = swa->sw_axf; bcopy(swa->sw_ictx, &ctx, axf->ctxsize); blksz = axf->blocksize; swe = &ses->swcr_encdec; exf = swe->sw_exf; KASSERT(axf->blocksize == exf->native_blocksize, ("%s: blocksize mismatch", __func__)); if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) return (EINVAL); /* Initialize the IV */ ivlen = AES_GCM_IV_LEN; bcopy(crp->crp_iv, iv, ivlen); /* Supply MAC with IV */ axf->Reinit(&ctx, iv, ivlen); /* Supply MAC with AAD */ crypto_cursor_init(&cc_in, &crp->crp_buf); crypto_cursor_advance(&cc_in, crp->crp_aad_start); for (resid = crp->crp_aad_length; resid > 0; resid -= len) { len = MIN(resid, blksz); crypto_cursor_copydata(&cc_in, len, blk); bzero(blk + len, blksz - len); axf->Update(&ctx, blk, blksz); } exf->reinit(swe->sw_kschedule, iv); /* Do encryption with MAC */ crypto_cursor_init(&cc_in, &crp->crp_buf); crypto_cursor_advance(&cc_in, crp->crp_payload_start); if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { crypto_cursor_init(&cc_out, &crp->crp_obuf); crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); } else cc_out = cc_in; for (resid = crp->crp_payload_length; resid > 0; resid -= len) { len = MIN(resid, blksz); if (len < blksz) bzero(blk, blksz); crypto_cursor_copydata(&cc_in, len, blk); if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { exf->encrypt(swe->sw_kschedule, blk, blk); axf->Update(&ctx, blk, len); crypto_cursor_copyback(&cc_out, len, blk); } else { axf->Update(&ctx, blk, len); } } /* length block */ bzero(blk, blksz); blkp = (uint32_t *)blk + 1; *blkp = htobe32(crp->crp_aad_length * 8); blkp = (uint32_t *)blk + 3; *blkp = htobe32(crp->crp_payload_length * 8); axf->Update(&ctx, blk, blksz); /* Finalize MAC */ axf->Final(aalg, &ctx); /* Validate tag */ error = 0; if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { u_char uaalg[AALG_MAX_RESULT_LEN]; crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, uaalg); r = timingsafe_bcmp(aalg, uaalg, swa->sw_mlen); explicit_bzero(uaalg, sizeof(uaalg)); if (r != 0) { error = EBADMSG; goto out; } /* tag matches, decrypt data */ crypto_cursor_init(&cc_in, &crp->crp_buf); crypto_cursor_advance(&cc_in, crp->crp_payload_start); for (resid = crp->crp_payload_length; resid > 0; resid -= len) { len = MIN(resid, blksz); if (len < blksz) bzero(blk, blksz); crypto_cursor_copydata(&cc_in, len, blk); exf->decrypt(swe->sw_kschedule, blk, blk); crypto_cursor_copyback(&cc_out, len, blk); } } else { /* Inject the authentication data */ crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, aalg); } out: explicit_bzero(blkbuf, sizeof(blkbuf)); explicit_bzero(aalg, sizeof(aalg)); explicit_bzero(iv, sizeof(iv)); return (error); } static int swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp) { uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; u_char *blk = (u_char *)blkbuf; u_char aalg[AALG_MAX_RESULT_LEN]; u_char iv[EALG_MAX_BLOCK_LEN]; struct crypto_buffer_cursor cc; union authctx ctx; struct swcr_auth *swa; struct auth_hash *axf; int blksz, error, ivlen, len, resid; swa = &ses->swcr_auth; axf = swa->sw_axf; bcopy(swa->sw_ictx, &ctx, axf->ctxsize); blksz = axf->blocksize; /* Initialize the IV */ ivlen = AES_CCM_IV_LEN; crypto_read_iv(crp, iv); /* * AES CCM-CBC-MAC needs to know the length of both the auth * data and payload data before doing the auth computation. */ ctx.aes_cbc_mac_ctx.authDataLength = crp->crp_payload_length; ctx.aes_cbc_mac_ctx.cryptDataLength = 0; axf->Reinit(&ctx, iv, ivlen); crypto_cursor_init(&cc, &crp->crp_buf); crypto_cursor_advance(&cc, crp->crp_aad_start); for (resid = crp->crp_payload_length; resid > 0; resid -= len) { len = MIN(resid, blksz); crypto_cursor_copydata(&cc, len, blk); bzero(blk + len, blksz - len); axf->Update(&ctx, blk, blksz); } /* Finalize MAC */ axf->Final(aalg, &ctx); error = 0; if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { u_char uaalg[AALG_MAX_RESULT_LEN]; crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, uaalg); if (timingsafe_bcmp(aalg, uaalg, swa->sw_mlen) != 0) error = EBADMSG; explicit_bzero(uaalg, sizeof(uaalg)); } else { /* Inject the authentication data */ crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, aalg); } explicit_bzero(blkbuf, sizeof(blkbuf)); explicit_bzero(aalg, sizeof(aalg)); explicit_bzero(iv, sizeof(iv)); return (error); } static int swcr_ccm(struct swcr_session *ses, struct cryptop *crp) { uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; u_char *blk = (u_char *)blkbuf; u_char aalg[AALG_MAX_RESULT_LEN]; u_char iv[EALG_MAX_BLOCK_LEN]; struct crypto_buffer_cursor cc_in, cc_out; union authctx ctx; struct swcr_auth *swa; struct swcr_encdec *swe; struct auth_hash *axf; struct enc_xform *exf; int blksz, error, ivlen, len, r, resid; swa = &ses->swcr_auth; axf = swa->sw_axf; bcopy(swa->sw_ictx, &ctx, axf->ctxsize); blksz = axf->blocksize; swe = &ses->swcr_encdec; exf = swe->sw_exf; KASSERT(axf->blocksize == exf->native_blocksize, ("%s: blocksize mismatch", __func__)); if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) return (EINVAL); /* Initialize the IV */ ivlen = AES_CCM_IV_LEN; bcopy(crp->crp_iv, iv, ivlen); /* * AES CCM-CBC-MAC needs to know the length of both the auth * data and payload data before doing the auth computation. */ ctx.aes_cbc_mac_ctx.authDataLength = crp->crp_aad_length; ctx.aes_cbc_mac_ctx.cryptDataLength = crp->crp_payload_length; /* Supply MAC with IV */ axf->Reinit(&ctx, iv, ivlen); /* Supply MAC with AAD */ crypto_cursor_init(&cc_in, &crp->crp_buf); crypto_cursor_advance(&cc_in, crp->crp_aad_start); for (resid = crp->crp_aad_length; resid > 0; resid -= len) { len = MIN(resid, blksz); crypto_cursor_copydata(&cc_in, len, blk); bzero(blk + len, blksz - len); axf->Update(&ctx, blk, blksz); } exf->reinit(swe->sw_kschedule, iv); /* Do encryption/decryption with MAC */ crypto_cursor_init(&cc_in, &crp->crp_buf); crypto_cursor_advance(&cc_in, crp->crp_payload_start); if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { crypto_cursor_init(&cc_out, &crp->crp_obuf); crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); } else cc_out = cc_in; for (resid = crp->crp_payload_length; resid > 0; resid -= len) { len = MIN(resid, blksz); if (len < blksz) bzero(blk, blksz); crypto_cursor_copydata(&cc_in, len, blk); if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { axf->Update(&ctx, blk, len); exf->encrypt(swe->sw_kschedule, blk, blk); crypto_cursor_copyback(&cc_out, len, blk); } else { /* * One of the problems with CCM+CBC is that * the authentication is done on the * unecncrypted data. As a result, we have to * decrypt the data twice: once to generate * the tag and a second time after the tag is * verified. */ exf->decrypt(swe->sw_kschedule, blk, blk); axf->Update(&ctx, blk, len); } } /* Finalize MAC */ axf->Final(aalg, &ctx); /* Validate tag */ error = 0; if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { u_char uaalg[AALG_MAX_RESULT_LEN]; crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, uaalg); r = timingsafe_bcmp(aalg, uaalg, swa->sw_mlen); explicit_bzero(uaalg, sizeof(uaalg)); if (r != 0) { error = EBADMSG; goto out; } /* tag matches, decrypt data */ exf->reinit(swe->sw_kschedule, iv); crypto_cursor_init(&cc_in, &crp->crp_buf); crypto_cursor_advance(&cc_in, crp->crp_payload_start); for (resid = crp->crp_payload_length; resid > 0; resid -= len) { len = MIN(resid, blksz); if (len < blksz) bzero(blk, blksz); crypto_cursor_copydata(&cc_in, len, blk); exf->decrypt(swe->sw_kschedule, blk, blk); crypto_cursor_copyback(&cc_out, len, blk); } } else { /* Inject the authentication data */ crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, aalg); } out: explicit_bzero(blkbuf, sizeof(blkbuf)); explicit_bzero(aalg, sizeof(aalg)); explicit_bzero(iv, sizeof(iv)); return (error); } /* * Apply a cipher and a digest to perform EtA. */ static int swcr_eta(struct swcr_session *ses, struct cryptop *crp) { int error; if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { error = swcr_encdec(ses, crp); if (error == 0) error = swcr_authcompute(ses, crp); } else { error = swcr_authcompute(ses, crp); if (error == 0) error = swcr_encdec(ses, crp); } return (error); } /* * Apply a compression/decompression algorithm */ static int swcr_compdec(struct swcr_session *ses, struct cryptop *crp) { u_int8_t *data, *out; struct comp_algo *cxf; int adj; u_int32_t result; cxf = ses->swcr_compdec.sw_cxf; /* We must handle the whole buffer of data in one time * then if there is not all the data in the mbuf, we must * copy in a buffer. */ data = malloc(crp->crp_payload_length, M_CRYPTO_DATA, M_NOWAIT); if (data == NULL) return (EINVAL); crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length, data); if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) result = cxf->compress(data, crp->crp_payload_length, &out); else result = cxf->decompress(data, crp->crp_payload_length, &out); free(data, M_CRYPTO_DATA); if (result == 0) return (EINVAL); crp->crp_olen = result; /* Check the compressed size when doing compression */ if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) { if (result >= crp->crp_payload_length) { /* Compression was useless, we lost time */ free(out, M_CRYPTO_DATA); return (0); } } /* Copy back the (de)compressed data. m_copyback is * extending the mbuf as necessary. */ crypto_copyback(crp, crp->crp_payload_start, result, out); if (result < crp->crp_payload_length) { switch (crp->crp_buf.cb_type) { case CRYPTO_BUF_MBUF: adj = result - crp->crp_payload_length; m_adj(crp->crp_buf.cb_mbuf, adj); break; case CRYPTO_BUF_UIO: { struct uio *uio = crp->crp_buf.cb_uio; int ind; adj = crp->crp_payload_length - result; ind = uio->uio_iovcnt - 1; while (adj > 0 && ind >= 0) { if (adj < uio->uio_iov[ind].iov_len) { uio->uio_iov[ind].iov_len -= adj; break; } adj -= uio->uio_iov[ind].iov_len; uio->uio_iov[ind].iov_len = 0; ind--; uio->uio_iovcnt--; } } break; default: break; } } free(out, M_CRYPTO_DATA); return 0; } static int swcr_setup_cipher(struct swcr_session *ses, const struct crypto_session_params *csp) { struct swcr_encdec *swe; struct enc_xform *txf; int error; swe = &ses->swcr_encdec; txf = crypto_cipher(csp); MPASS(txf->ivsize == csp->csp_ivlen); if (txf->ctxsize != 0) { swe->sw_kschedule = malloc(txf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); if (swe->sw_kschedule == NULL) return (ENOMEM); } if (csp->csp_cipher_key != NULL) { error = txf->setkey(swe->sw_kschedule, csp->csp_cipher_key, csp->csp_cipher_klen); if (error) return (error); } swe->sw_exf = txf; return (0); } static int swcr_setup_auth(struct swcr_session *ses, const struct crypto_session_params *csp) { struct swcr_auth *swa; struct auth_hash *axf; swa = &ses->swcr_auth; axf = crypto_auth_hash(csp); swa->sw_axf = axf; if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) return (EINVAL); if (csp->csp_auth_mlen == 0) swa->sw_mlen = axf->hashsize; else swa->sw_mlen = csp->csp_auth_mlen; swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); if (swa->sw_ictx == NULL) return (ENOBUFS); switch (csp->csp_auth_alg) { case CRYPTO_SHA1_HMAC: case CRYPTO_SHA2_224_HMAC: case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: case CRYPTO_NULL_HMAC: case CRYPTO_RIPEMD160_HMAC: swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); if (swa->sw_octx == NULL) return (ENOBUFS); if (csp->csp_auth_key != NULL) { swcr_authprepare(axf, swa, csp->csp_auth_key, csp->csp_auth_klen); } if (csp->csp_mode == CSP_MODE_DIGEST) ses->swcr_process = swcr_authcompute; break; case CRYPTO_SHA1: case CRYPTO_SHA2_224: case CRYPTO_SHA2_256: case CRYPTO_SHA2_384: case CRYPTO_SHA2_512: axf->Init(swa->sw_ictx); if (csp->csp_mode == CSP_MODE_DIGEST) ses->swcr_process = swcr_authcompute; break; case CRYPTO_AES_NIST_GMAC: axf->Init(swa->sw_ictx); axf->Setkey(swa->sw_ictx, csp->csp_auth_key, csp->csp_auth_klen); if (csp->csp_mode == CSP_MODE_DIGEST) ses->swcr_process = swcr_gmac; break; case CRYPTO_POLY1305: case CRYPTO_BLAKE2B: case CRYPTO_BLAKE2S: /* * Blake2b and Blake2s support an optional key but do * not require one. */ if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL) axf->Setkey(swa->sw_ictx, csp->csp_auth_key, csp->csp_auth_klen); axf->Init(swa->sw_ictx); if (csp->csp_mode == CSP_MODE_DIGEST) ses->swcr_process = swcr_authcompute; break; case CRYPTO_AES_CCM_CBC_MAC: axf->Init(swa->sw_ictx); axf->Setkey(swa->sw_ictx, csp->csp_auth_key, csp->csp_auth_klen); if (csp->csp_mode == CSP_MODE_DIGEST) ses->swcr_process = swcr_ccm_cbc_mac; break; } return (0); } static int swcr_setup_gcm(struct swcr_session *ses, const struct crypto_session_params *csp) { struct swcr_auth *swa; struct auth_hash *axf; if (csp->csp_ivlen != AES_GCM_IV_LEN) return (EINVAL); /* First, setup the auth side. */ swa = &ses->swcr_auth; switch (csp->csp_cipher_klen * 8) { case 128: axf = &auth_hash_nist_gmac_aes_128; break; case 192: axf = &auth_hash_nist_gmac_aes_192; break; case 256: axf = &auth_hash_nist_gmac_aes_256; break; default: return (EINVAL); } swa->sw_axf = axf; if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) return (EINVAL); if (csp->csp_auth_mlen == 0) swa->sw_mlen = axf->hashsize; else swa->sw_mlen = csp->csp_auth_mlen; swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); if (swa->sw_ictx == NULL) return (ENOBUFS); axf->Init(swa->sw_ictx); if (csp->csp_cipher_key != NULL) axf->Setkey(swa->sw_ictx, csp->csp_cipher_key, csp->csp_cipher_klen); /* Second, setup the cipher side. */ return (swcr_setup_cipher(ses, csp)); } static int swcr_setup_ccm(struct swcr_session *ses, const struct crypto_session_params *csp) { struct swcr_auth *swa; struct auth_hash *axf; if (csp->csp_ivlen != AES_CCM_IV_LEN) return (EINVAL); /* First, setup the auth side. */ swa = &ses->swcr_auth; switch (csp->csp_cipher_klen * 8) { case 128: axf = &auth_hash_ccm_cbc_mac_128; break; case 192: axf = &auth_hash_ccm_cbc_mac_192; break; case 256: axf = &auth_hash_ccm_cbc_mac_256; break; default: return (EINVAL); } swa->sw_axf = axf; if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) return (EINVAL); if (csp->csp_auth_mlen == 0) swa->sw_mlen = axf->hashsize; else swa->sw_mlen = csp->csp_auth_mlen; swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); if (swa->sw_ictx == NULL) return (ENOBUFS); axf->Init(swa->sw_ictx); if (csp->csp_cipher_key != NULL) axf->Setkey(swa->sw_ictx, csp->csp_cipher_key, csp->csp_cipher_klen); /* Second, setup the cipher side. */ return (swcr_setup_cipher(ses, csp)); } static bool swcr_auth_supported(const struct crypto_session_params *csp) { struct auth_hash *axf; axf = crypto_auth_hash(csp); if (axf == NULL) return (false); switch (csp->csp_auth_alg) { case CRYPTO_SHA1_HMAC: case CRYPTO_SHA2_224_HMAC: case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: case CRYPTO_NULL_HMAC: case CRYPTO_RIPEMD160_HMAC: break; case CRYPTO_AES_NIST_GMAC: switch (csp->csp_auth_klen * 8) { case 128: case 192: case 256: break; default: return (false); } if (csp->csp_auth_key == NULL) return (false); if (csp->csp_ivlen != AES_GCM_IV_LEN) return (false); break; case CRYPTO_POLY1305: if (csp->csp_auth_klen != POLY1305_KEY_LEN) return (false); break; case CRYPTO_AES_CCM_CBC_MAC: switch (csp->csp_auth_klen * 8) { case 128: case 192: case 256: break; default: return (false); } if (csp->csp_auth_key == NULL) return (false); if (csp->csp_ivlen != AES_CCM_IV_LEN) return (false); break; } return (true); } static bool swcr_cipher_supported(const struct crypto_session_params *csp) { struct enc_xform *txf; txf = crypto_cipher(csp); if (txf == NULL) return (false); if (csp->csp_cipher_alg != CRYPTO_NULL_CBC && txf->ivsize != csp->csp_ivlen) return (false); return (true); } static int swcr_probesession(device_t dev, const struct crypto_session_params *csp) { if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT)) != 0) return (EINVAL); switch (csp->csp_mode) { case CSP_MODE_COMPRESS: switch (csp->csp_cipher_alg) { case CRYPTO_DEFLATE_COMP: break; default: return (EINVAL); } break; case CSP_MODE_CIPHER: switch (csp->csp_cipher_alg) { case CRYPTO_AES_NIST_GCM_16: case CRYPTO_AES_CCM_16: return (EINVAL); default: if (!swcr_cipher_supported(csp)) return (EINVAL); break; } break; case CSP_MODE_DIGEST: if (!swcr_auth_supported(csp)) return (EINVAL); break; case CSP_MODE_AEAD: switch (csp->csp_cipher_alg) { case CRYPTO_AES_NIST_GCM_16: case CRYPTO_AES_CCM_16: break; default: return (EINVAL); } break; case CSP_MODE_ETA: /* AEAD algorithms cannot be used for EtA. */ switch (csp->csp_cipher_alg) { case CRYPTO_AES_NIST_GCM_16: case CRYPTO_AES_CCM_16: return (EINVAL); } switch (csp->csp_auth_alg) { case CRYPTO_AES_NIST_GMAC: case CRYPTO_AES_CCM_CBC_MAC: return (EINVAL); } if (!swcr_cipher_supported(csp) || !swcr_auth_supported(csp)) return (EINVAL); break; default: return (EINVAL); } return (CRYPTODEV_PROBE_SOFTWARE); } /* * Generate a new software session. */ static int swcr_newsession(device_t dev, crypto_session_t cses, const struct crypto_session_params *csp) { struct swcr_session *ses; struct swcr_encdec *swe; struct swcr_auth *swa; struct comp_algo *cxf; int error; ses = crypto_get_driver_session(cses); mtx_init(&ses->swcr_lock, "swcr session lock", NULL, MTX_DEF); error = 0; swe = &ses->swcr_encdec; swa = &ses->swcr_auth; switch (csp->csp_mode) { case CSP_MODE_COMPRESS: switch (csp->csp_cipher_alg) { case CRYPTO_DEFLATE_COMP: cxf = &comp_algo_deflate; break; #ifdef INVARIANTS default: panic("bad compression algo"); #endif } ses->swcr_compdec.sw_cxf = cxf; ses->swcr_process = swcr_compdec; break; case CSP_MODE_CIPHER: switch (csp->csp_cipher_alg) { case CRYPTO_NULL_CBC: ses->swcr_process = swcr_null; break; #ifdef INVARIANTS case CRYPTO_AES_NIST_GCM_16: case CRYPTO_AES_CCM_16: panic("bad cipher algo"); #endif default: error = swcr_setup_cipher(ses, csp); if (error == 0) ses->swcr_process = swcr_encdec; } break; case CSP_MODE_DIGEST: error = swcr_setup_auth(ses, csp); break; case CSP_MODE_AEAD: switch (csp->csp_cipher_alg) { case CRYPTO_AES_NIST_GCM_16: error = swcr_setup_gcm(ses, csp); if (error == 0) ses->swcr_process = swcr_gcm; break; case CRYPTO_AES_CCM_16: error = swcr_setup_ccm(ses, csp); if (error == 0) ses->swcr_process = swcr_ccm; break; #ifdef INVARIANTS default: panic("bad aead algo"); #endif } break; case CSP_MODE_ETA: #ifdef INVARIANTS switch (csp->csp_cipher_alg) { case CRYPTO_AES_NIST_GCM_16: case CRYPTO_AES_CCM_16: panic("bad eta cipher algo"); } switch (csp->csp_auth_alg) { case CRYPTO_AES_NIST_GMAC: case CRYPTO_AES_CCM_CBC_MAC: panic("bad eta auth algo"); } #endif error = swcr_setup_auth(ses, csp); if (error) break; if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) { /* Effectively degrade to digest mode. */ ses->swcr_process = swcr_authcompute; break; } error = swcr_setup_cipher(ses, csp); if (error == 0) ses->swcr_process = swcr_eta; break; default: error = EINVAL; } if (error) swcr_freesession(dev, cses); return (error); } static void swcr_freesession(device_t dev, crypto_session_t cses) { struct swcr_session *ses; struct swcr_auth *swa; struct auth_hash *axf; ses = crypto_get_driver_session(cses); mtx_destroy(&ses->swcr_lock); zfree(ses->swcr_encdec.sw_kschedule, M_CRYPTO_DATA); axf = ses->swcr_auth.sw_axf; if (axf != NULL) { swa = &ses->swcr_auth; if (swa->sw_ictx != NULL) { explicit_bzero(swa->sw_ictx, axf->ctxsize); free(swa->sw_ictx, M_CRYPTO_DATA); } if (swa->sw_octx != NULL) { explicit_bzero(swa->sw_octx, axf->ctxsize); free(swa->sw_octx, M_CRYPTO_DATA); } } } /* * Process a software request. */ static int swcr_process(device_t dev, struct cryptop *crp, int hint) { struct swcr_session *ses; ses = crypto_get_driver_session(crp->crp_session); mtx_lock(&ses->swcr_lock); crp->crp_etype = ses->swcr_process(ses, crp); mtx_unlock(&ses->swcr_lock); crypto_done(crp); return (0); } static void swcr_identify(driver_t *drv, device_t parent) { /* NB: order 10 is so we get attached after h/w devices */ if (device_find_child(parent, "cryptosoft", -1) == NULL && BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0) panic("cryptosoft: could not attach"); } static int swcr_probe(device_t dev) { device_set_desc(dev, "software crypto"); return (BUS_PROBE_NOWILDCARD); } static int swcr_attach(device_t dev) { swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session), CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); if (swcr_id < 0) { device_printf(dev, "cannot initialize!"); return (ENXIO); } return (0); } static int swcr_detach(device_t dev) { crypto_unregister_all(swcr_id); return 0; } static device_method_t swcr_methods[] = { DEVMETHOD(device_identify, swcr_identify), DEVMETHOD(device_probe, swcr_probe), DEVMETHOD(device_attach, swcr_attach), DEVMETHOD(device_detach, swcr_detach), DEVMETHOD(cryptodev_probesession, swcr_probesession), DEVMETHOD(cryptodev_newsession, swcr_newsession), DEVMETHOD(cryptodev_freesession,swcr_freesession), DEVMETHOD(cryptodev_process, swcr_process), {0, 0}, }; static driver_t swcr_driver = { "cryptosoft", swcr_methods, 0, /* NB: no softc */ }; static devclass_t swcr_devclass; /* * NB: We explicitly reference the crypto module so we * get the necessary ordering when built as a loadable * module. This is required because we bundle the crypto * module code together with the cryptosoft driver (otherwise * normal module dependencies would handle things). */ extern int crypto_modevent(struct module *, int, void *); /* XXX where to attach */ DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0); MODULE_VERSION(cryptosoft, 1); MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1); Index: head/sys/opencrypto/gmac.c =================================================================== --- head/sys/opencrypto/gmac.c (revision 362027) +++ head/sys/opencrypto/gmac.c (revision 362028) @@ -1,119 +1,131 @@ /*- * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * This software was developed by John-Mark Gurney under * the sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * */ #include #include #include #include void -AES_GMAC_Init(struct aes_gmac_ctx *agc) +AES_GMAC_Init(void *ctx) { + struct aes_gmac_ctx *agc; + agc = ctx; bzero(agc, sizeof *agc); } void -AES_GMAC_Setkey(struct aes_gmac_ctx *agc, const uint8_t *key, uint16_t klen) +AES_GMAC_Setkey(void *ctx, const uint8_t *key, u_int klen) { + struct aes_gmac_ctx *agc; const uint8_t zeros[GMAC_BLOCK_LEN] = {}; struct gf128 h; uint8_t hbuf[GMAC_BLOCK_LEN]; + agc = ctx; agc->rounds = rijndaelKeySetupEnc(agc->keysched, key, klen * 8); rijndaelEncrypt(agc->keysched, agc->rounds, zeros, hbuf); h = gf128_read(hbuf); gf128_genmultable4(h, &agc->ghashtbl); explicit_bzero(&h, sizeof h); explicit_bzero(hbuf, sizeof hbuf); } void -AES_GMAC_Reinit(struct aes_gmac_ctx *agc, const uint8_t *iv, uint16_t ivlen) +AES_GMAC_Reinit(void *ctx, const uint8_t *iv, u_int ivlen) { + struct aes_gmac_ctx *agc; + agc = ctx; KASSERT(ivlen <= sizeof agc->counter, ("passed ivlen too large!")); bcopy(iv, agc->counter, ivlen); } int -AES_GMAC_Update(struct aes_gmac_ctx *agc, const uint8_t *data, uint16_t len) +AES_GMAC_Update(void *ctx, const void *vdata, u_int len) { + struct aes_gmac_ctx *agc; + const uint8_t *data; struct gf128 v; uint8_t buf[GMAC_BLOCK_LEN] = {}; int i; + agc = ctx; + data = vdata; v = agc->hash; while (len > 0) { if (len >= 4*GMAC_BLOCK_LEN) { i = 4*GMAC_BLOCK_LEN; v = gf128_mul4b(v, data, &agc->ghashtbl); } else if (len >= GMAC_BLOCK_LEN) { i = GMAC_BLOCK_LEN; v = gf128_add(v, gf128_read(data)); v = gf128_mul(v, &agc->ghashtbl.tbls[0]); } else { i = len; bcopy(data, buf, i); v = gf128_add(v, gf128_read(&buf[0])); v = gf128_mul(v, &agc->ghashtbl.tbls[0]); explicit_bzero(buf, sizeof buf); } len -= i; data += i; } agc->hash = v; explicit_bzero(&v, sizeof v); return (0); } void -AES_GMAC_Final(uint8_t digest[GMAC_DIGEST_LEN], struct aes_gmac_ctx *agc) +AES_GMAC_Final(uint8_t *digest, void *ctx) { + struct aes_gmac_ctx *agc; uint8_t enccntr[GMAC_BLOCK_LEN]; struct gf128 a; /* XXX - zero additional bytes? */ + agc = ctx; agc->counter[GMAC_BLOCK_LEN - 1] = 1; rijndaelEncrypt(agc->keysched, agc->rounds, agc->counter, enccntr); a = gf128_add(agc->hash, gf128_read(enccntr)); gf128_write(a, digest); explicit_bzero(enccntr, sizeof enccntr); } Index: head/sys/opencrypto/gmac.h =================================================================== --- head/sys/opencrypto/gmac.h (revision 362027) +++ head/sys/opencrypto/gmac.h (revision 362028) @@ -1,56 +1,56 @@ /*- * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * This software was developed by John-Mark Gurney under * the sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * */ #ifndef _GMAC_H_ #define _GMAC_H_ #include "gfmult.h" #include #define GMAC_BLOCK_LEN 16 #define GMAC_DIGEST_LEN 16 struct aes_gmac_ctx { struct gf128table4 ghashtbl; struct gf128 hash; uint32_t keysched[4*(RIJNDAEL_MAXNR + 1)]; uint8_t counter[GMAC_BLOCK_LEN]; int rounds; }; -void AES_GMAC_Init(struct aes_gmac_ctx *); -void AES_GMAC_Setkey(struct aes_gmac_ctx *, const uint8_t *, uint16_t); -void AES_GMAC_Reinit(struct aes_gmac_ctx *, const uint8_t *, uint16_t); -int AES_GMAC_Update(struct aes_gmac_ctx *, const uint8_t *, uint16_t); -void AES_GMAC_Final(uint8_t [GMAC_DIGEST_LEN], struct aes_gmac_ctx *); +void AES_GMAC_Init(void *); +void AES_GMAC_Setkey(void *, const uint8_t *, u_int); +void AES_GMAC_Reinit(void *, const uint8_t *, u_int); +int AES_GMAC_Update(void *, const void *, u_int); +void AES_GMAC_Final(uint8_t *, void *); #endif /* _GMAC_H_ */ Index: head/sys/opencrypto/xform_auth.h =================================================================== --- head/sys/opencrypto/xform_auth.h (revision 362027) +++ head/sys/opencrypto/xform_auth.h (revision 362028) @@ -1,99 +1,99 @@ /* $FreeBSD$ */ /* $OpenBSD: xform.h,v 1.8 2001/08/28 12:20:43 ben Exp $ */ /*- * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * * This code was written by Angelos D. Keromytis in Athens, Greece, in * February 2000. Network Security Technologies Inc. (NSTI) kindly * supported the development of this code. * * Copyright (c) 2000 Angelos D. Keromytis * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software without fee * is hereby granted, provided that this entire notice is included in * all source code copies of any software which is or includes a copy or * modification of this software. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #ifndef _CRYPTO_XFORM_AUTH_H_ #define _CRYPTO_XFORM_AUTH_H_ #include #include #include #include #include #include #include #include #include #include #include /* XXX use a define common with other hash stuff ! */ #define AH_ALEN_MAX 64 /* max authenticator hash length */ /* Declarations */ struct auth_hash { int type; char *name; u_int16_t keysize; u_int16_t hashsize; u_int16_t ctxsize; u_int16_t blocksize; void (*Init) (void *); - void (*Setkey) (void *, const u_int8_t *, u_int16_t); - void (*Reinit) (void *, const u_int8_t *, u_int16_t); - int (*Update) (void *, const u_int8_t *, u_int16_t); + void (*Setkey) (void *, const uint8_t *, u_int); + void (*Reinit) (void *, const uint8_t *, u_int); + int (*Update) (void *, const void *, u_int); void (*Final) (u_int8_t *, void *); }; extern struct auth_hash auth_hash_null; extern struct auth_hash auth_hash_hmac_sha1; extern struct auth_hash auth_hash_hmac_ripemd_160; extern struct auth_hash auth_hash_hmac_sha2_224; extern struct auth_hash auth_hash_hmac_sha2_256; extern struct auth_hash auth_hash_hmac_sha2_384; extern struct auth_hash auth_hash_hmac_sha2_512; extern struct auth_hash auth_hash_sha1; extern struct auth_hash auth_hash_sha2_224; extern struct auth_hash auth_hash_sha2_256; extern struct auth_hash auth_hash_sha2_384; extern struct auth_hash auth_hash_sha2_512; extern struct auth_hash auth_hash_nist_gmac_aes_128; extern struct auth_hash auth_hash_nist_gmac_aes_192; extern struct auth_hash auth_hash_nist_gmac_aes_256; extern struct auth_hash auth_hash_blake2b; extern struct auth_hash auth_hash_blake2s; extern struct auth_hash auth_hash_poly1305; extern struct auth_hash auth_hash_ccm_cbc_mac_128; extern struct auth_hash auth_hash_ccm_cbc_mac_192; extern struct auth_hash auth_hash_ccm_cbc_mac_256; union authctx { SHA1_CTX sha1ctx; RMD160_CTX rmd160ctx; SHA224_CTX sha224ctx; SHA256_CTX sha256ctx; SHA384_CTX sha384ctx; SHA512_CTX sha512ctx; struct aes_gmac_ctx aes_gmac_ctx; struct aes_cbc_mac_ctx aes_cbc_mac_ctx; }; #endif /* _CRYPTO_XFORM_AUTH_H_ */ Index: head/sys/opencrypto/xform_cbc_mac.c =================================================================== --- head/sys/opencrypto/xform_cbc_mac.c (revision 362027) +++ head/sys/opencrypto/xform_cbc_mac.c (revision 362028) @@ -1,55 +1,46 @@ #include __FBSDID("$FreeBSD$"); #include #include /* Authentication instances */ struct auth_hash auth_hash_ccm_cbc_mac_128 = { .type = CRYPTO_AES_CCM_CBC_MAC, .name = "CBC-CCM-AES-128", .keysize = AES_128_CBC_MAC_KEY_LEN, .hashsize = AES_CBC_MAC_HASH_LEN, .ctxsize = sizeof(struct aes_cbc_mac_ctx), .blocksize = CCM_CBC_BLOCK_LEN, - .Init = (void (*)(void *)) AES_CBC_MAC_Init, - .Setkey = - (void (*)(void *, const u_int8_t *, u_int16_t))AES_CBC_MAC_Setkey, - .Reinit = - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_CBC_MAC_Reinit, - .Update = - (int (*)(void *, const u_int8_t *, u_int16_t)) AES_CBC_MAC_Update, - .Final = (void (*)(u_int8_t *, void *)) AES_CBC_MAC_Final, + .Init = AES_CBC_MAC_Init, + .Setkey = AES_CBC_MAC_Setkey, + .Reinit = AES_CBC_MAC_Reinit, + .Update = AES_CBC_MAC_Update, + .Final = AES_CBC_MAC_Final, }; struct auth_hash auth_hash_ccm_cbc_mac_192 = { .type = CRYPTO_AES_CCM_CBC_MAC, .name = "CBC-CCM-AES-192", .keysize = AES_192_CBC_MAC_KEY_LEN, .hashsize = AES_CBC_MAC_HASH_LEN, .ctxsize = sizeof(struct aes_cbc_mac_ctx), .blocksize = CCM_CBC_BLOCK_LEN, - .Init = (void (*)(void *)) AES_CBC_MAC_Init, - .Setkey = - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_CBC_MAC_Setkey, - .Reinit = - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_CBC_MAC_Reinit, - .Update = - (int (*)(void *, const u_int8_t *, u_int16_t)) AES_CBC_MAC_Update, - .Final = (void (*)(u_int8_t *, void *)) AES_CBC_MAC_Final, + .Init = AES_CBC_MAC_Init, + .Setkey = AES_CBC_MAC_Setkey, + .Reinit = AES_CBC_MAC_Reinit, + .Update = AES_CBC_MAC_Update, + .Final = AES_CBC_MAC_Final, }; struct auth_hash auth_hash_ccm_cbc_mac_256 = { .type = CRYPTO_AES_CCM_CBC_MAC, .name = "CBC-CCM-AES-256", .keysize = AES_256_CBC_MAC_KEY_LEN, .hashsize = AES_CBC_MAC_HASH_LEN, .ctxsize = sizeof(struct aes_cbc_mac_ctx), .blocksize = CCM_CBC_BLOCK_LEN, - .Init = (void (*)(void *)) AES_CBC_MAC_Init, - .Setkey = - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_CBC_MAC_Setkey, - .Reinit = - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_CBC_MAC_Reinit, - .Update = - (int (*)(void *, const u_int8_t *, u_int16_t)) AES_CBC_MAC_Update, - .Final = (void (*)(u_int8_t *, void *)) AES_CBC_MAC_Final, + .Init = AES_CBC_MAC_Init, + .Setkey = AES_CBC_MAC_Setkey, + .Reinit = AES_CBC_MAC_Reinit, + .Update = AES_CBC_MAC_Update, + .Final = AES_CBC_MAC_Final, }; Index: head/sys/opencrypto/xform_gmac.c =================================================================== --- head/sys/opencrypto/xform_gmac.c (revision 362027) +++ head/sys/opencrypto/xform_gmac.c (revision 362028) @@ -1,98 +1,107 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * AES XTS implementation in 2008 by Damien Miller * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * * Copyright (C) 2008, Damien Miller * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include /* Encryption instances */ struct enc_xform enc_xform_aes_nist_gmac = { .type = CRYPTO_AES_NIST_GMAC, .name = "AES-GMAC", .blocksize = AES_ICM_BLOCK_LEN, .ivsize = AES_GCM_IV_LEN, .minkey = AES_MIN_KEY, .maxkey = AES_MAX_KEY, }; /* Authentication instances */ struct auth_hash auth_hash_nist_gmac_aes_128 = { - CRYPTO_AES_NIST_GMAC, "GMAC-AES-128", - AES_128_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx), - GMAC_BLOCK_LEN, - (void (*)(void *)) AES_GMAC_Init, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit, - (int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update, - (void (*)(u_int8_t *, void *)) AES_GMAC_Final + .type = CRYPTO_AES_NIST_GMAC, + .name = "GMAC-AES-128", + .keysize = AES_128_GMAC_KEY_LEN, + .hashsize = AES_GMAC_HASH_LEN, + .ctxsize = sizeof(struct aes_gmac_ctx), + .blocksize = GMAC_BLOCK_LEN, + .Init = AES_GMAC_Init, + .Setkey = AES_GMAC_Setkey, + .Reinit = AES_GMAC_Reinit, + .Update = AES_GMAC_Update, + .Final = AES_GMAC_Final, }; struct auth_hash auth_hash_nist_gmac_aes_192 = { - CRYPTO_AES_NIST_GMAC, "GMAC-AES-192", - AES_192_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx), - GMAC_BLOCK_LEN, - (void (*)(void *)) AES_GMAC_Init, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit, - (int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update, - (void (*)(u_int8_t *, void *)) AES_GMAC_Final + .type = CRYPTO_AES_NIST_GMAC, + .name = "GMAC-AES-192", + .keysize = AES_192_GMAC_KEY_LEN, + .hashsize = AES_GMAC_HASH_LEN, + .ctxsize = sizeof(struct aes_gmac_ctx), + .blocksize = GMAC_BLOCK_LEN, + .Init = AES_GMAC_Init, + .Setkey = AES_GMAC_Setkey, + .Reinit = AES_GMAC_Reinit, + .Update = AES_GMAC_Update, + .Final = AES_GMAC_Final, }; struct auth_hash auth_hash_nist_gmac_aes_256 = { - CRYPTO_AES_NIST_GMAC, "GMAC-AES-256", - AES_256_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx), - GMAC_BLOCK_LEN, - (void (*)(void *)) AES_GMAC_Init, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit, - (int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update, - (void (*)(u_int8_t *, void *)) AES_GMAC_Final + .type = CRYPTO_AES_NIST_GMAC, + .name = "GMAC-AES-256", + .keysize = AES_256_GMAC_KEY_LEN, + .hashsize = AES_GMAC_HASH_LEN, + .ctxsize = sizeof(struct aes_gmac_ctx), + .blocksize = GMAC_BLOCK_LEN, + .Init = AES_GMAC_Init, + .Setkey = AES_GMAC_Setkey, + .Reinit = AES_GMAC_Reinit, + .Update = AES_GMAC_Update, + .Final = AES_GMAC_Final, }; Index: head/sys/opencrypto/xform_null.c =================================================================== --- head/sys/opencrypto/xform_null.c (revision 362027) +++ head/sys/opencrypto/xform_null.c (revision 362028) @@ -1,132 +1,132 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * AES XTS implementation in 2008 by Damien Miller * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * * Copyright (C) 2008, Damien Miller * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include static int null_setkey(void *, const u_int8_t *, int); static void null_crypt(void *, const uint8_t *, uint8_t *); static void null_init(void *); -static void null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len); -static int null_update(void *, const u_int8_t *, u_int16_t); +static void null_reinit(void *ctx, const uint8_t *buf, u_int len); +static int null_update(void *, const void *, u_int); static void null_final(u_int8_t *, void *); /* Encryption instances */ struct enc_xform enc_xform_null = { .type = CRYPTO_NULL_CBC, .name = "NULL", /* NB: blocksize of 4 is to generate a properly aligned ESP header */ .blocksize = NULL_BLOCK_LEN, .ivsize = 0, .minkey = NULL_MIN_KEY, .maxkey = NULL_MAX_KEY, .encrypt = null_crypt, .decrypt = null_crypt, .setkey = null_setkey, }; /* Authentication instances */ struct auth_hash auth_hash_null = { .type = CRYPTO_NULL_HMAC, .name = "NULL-HMAC", .keysize = 0, .hashsize = NULL_HASH_LEN, .ctxsize = sizeof(int), /* NB: context isn't used */ .blocksize = NULL_HMAC_BLOCK_LEN, .Init = null_init, .Setkey = null_reinit, .Reinit = null_reinit, .Update = null_update, .Final = null_final, }; /* * Encryption wrapper routines. */ static void null_crypt(void *key, const uint8_t *in, uint8_t *out) { } static int null_setkey(void *sched, const uint8_t *key, int len) { return (0); } /* * And now for auth. */ static void null_init(void *ctx) { } static void -null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len) +null_reinit(void *ctx, const uint8_t *buf, u_int len) { } static int -null_update(void *ctx, const u_int8_t *buf, u_int16_t len) +null_update(void *ctx, const void *buf, u_int len) { return 0; } static void null_final(u_int8_t *buf, void *ctx) { if (buf != (u_int8_t *) 0) bzero(buf, 12); } Index: head/sys/opencrypto/xform_poly1305.c =================================================================== --- head/sys/opencrypto/xform_poly1305.c (revision 362027) +++ head/sys/opencrypto/xform_poly1305.c (revision 362028) @@ -1,91 +1,91 @@ /* This file is in the public domain. */ #include __FBSDID("$FreeBSD$"); #include #include #include struct poly1305_xform_ctx { struct crypto_onetimeauth_poly1305_state state; }; CTASSERT(sizeof(union authctx) >= sizeof(struct poly1305_xform_ctx)); CTASSERT(POLY1305_KEY_LEN == crypto_onetimeauth_poly1305_KEYBYTES); CTASSERT(POLY1305_HASH_LEN == crypto_onetimeauth_poly1305_BYTES); void -Poly1305_Init(struct poly1305_xform_ctx *polyctx) +Poly1305_Init(void *polyctx) { /* Nop */ } void Poly1305_Setkey(struct poly1305_xform_ctx *polyctx, const uint8_t key[__min_size(POLY1305_KEY_LEN)], size_t klen) { int rc; if (klen != POLY1305_KEY_LEN) panic("%s: Bogus keylen: %u bytes", __func__, (unsigned)klen); rc = crypto_onetimeauth_poly1305_init(&polyctx->state, key); if (rc != 0) panic("%s: Invariant violated: %d", __func__, rc); } static void -xform_Poly1305_Setkey(void *ctx, const uint8_t *key, uint16_t klen) +xform_Poly1305_Setkey(void *ctx, const uint8_t *key, u_int klen) { Poly1305_Setkey(ctx, key, klen); } int Poly1305_Update(struct poly1305_xform_ctx *polyctx, const void *data, size_t len) { int rc; rc = crypto_onetimeauth_poly1305_update(&polyctx->state, data, len); if (rc != 0) panic("%s: Invariant violated: %d", __func__, rc); return (0); } static int -xform_Poly1305_Update(void *ctx, const uint8_t *data, uint16_t len) +xform_Poly1305_Update(void *ctx, const void *data, u_int len) { return (Poly1305_Update(ctx, data, len)); } void Poly1305_Final(uint8_t digest[__min_size(POLY1305_HASH_LEN)], struct poly1305_xform_ctx *polyctx) { int rc; rc = crypto_onetimeauth_poly1305_final(&polyctx->state, digest); if (rc != 0) panic("%s: Invariant violated: %d", __func__, rc); } static void xform_Poly1305_Final(uint8_t *digest, void *ctx) { Poly1305_Final(digest, ctx); } struct auth_hash auth_hash_poly1305 = { .type = CRYPTO_POLY1305, .name = "Poly-1305", .keysize = POLY1305_KEY_LEN, .hashsize = POLY1305_HASH_LEN, .ctxsize = sizeof(struct poly1305_xform_ctx), .blocksize = crypto_onetimeauth_poly1305_BYTES, - .Init = (void *)Poly1305_Init, + .Init = Poly1305_Init, .Setkey = xform_Poly1305_Setkey, .Update = xform_Poly1305_Update, .Final = xform_Poly1305_Final, }; Index: head/sys/opencrypto/xform_poly1305.h =================================================================== --- head/sys/opencrypto/xform_poly1305.h (revision 362027) +++ head/sys/opencrypto/xform_poly1305.h (revision 362028) @@ -1,16 +1,16 @@ /* This file is in the public domain. */ /* $FreeBSD$ */ #pragma once #include struct poly1305_xform_ctx; -void Poly1305_Init(struct poly1305_xform_ctx *); +void Poly1305_Init(void *); void Poly1305_Setkey(struct poly1305_xform_ctx *, const uint8_t [__min_size(32)], size_t); int Poly1305_Update(struct poly1305_xform_ctx *, const void *, size_t); void Poly1305_Final(uint8_t [__min_size(16)], struct poly1305_xform_ctx *); Index: head/sys/opencrypto/xform_rmd160.c =================================================================== --- head/sys/opencrypto/xform_rmd160.c (revision 362027) +++ head/sys/opencrypto/xform_rmd160.c (revision 362028) @@ -1,79 +1,90 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * AES XTS implementation in 2008 by Damien Miller * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * * Copyright (C) 2008, Damien Miller * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include -static int RMD160Update_int(void *, const u_int8_t *, u_int16_t); +static void RMD160Init_int(void *); +static int RMD160Update_int(void *, const void *, u_int); +static void RMD160Final_int(uint8_t *, void *); /* Authentication instances */ struct auth_hash auth_hash_hmac_ripemd_160 = { .type = CRYPTO_RIPEMD160_HMAC, .name = "HMAC-RIPEMD-160", .keysize = RIPEMD160_BLOCK_LEN, .hashsize = RIPEMD160_HASH_LEN, .ctxsize = sizeof(RMD160_CTX), .blocksize = RIPEMD160_BLOCK_LEN, - .Init = (void (*)(void *)) RMD160Init, + .Init = RMD160Init_int, .Update = RMD160Update_int, - .Final = (void (*)(u_int8_t *, void *)) RMD160Final, + .Final = RMD160Final_int, }; -/* - * And now for auth. - */ +static void +RMD160Init_int(void *ctx) +{ + RMD160Init(ctx); +} + static int -RMD160Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +RMD160Update_int(void *ctx, const void *buf, u_int len) { RMD160Update(ctx, buf, len); return 0; +} + +static void +RMD160Final_int(uint8_t *digest, void *ctx) +{ + RMD160Final(digest, ctx); } Index: head/sys/opencrypto/xform_sha1.c =================================================================== --- head/sys/opencrypto/xform_sha1.c (revision 362027) +++ head/sys/opencrypto/xform_sha1.c (revision 362028) @@ -1,105 +1,105 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * AES XTS implementation in 2008 by Damien Miller * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * * Copyright (C) 2008, Damien Miller * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include static void SHA1Init_int(void *); -static int SHA1Update_int(void *, const u_int8_t *, u_int16_t); +static int SHA1Update_int(void *, const void *, u_int); static void SHA1Final_int(u_int8_t *, void *); /* Plain hash */ struct auth_hash auth_hash_sha1 = { .type = CRYPTO_SHA1, .name = "SHA1", .hashsize = SHA1_HASH_LEN, .ctxsize = sizeof(SHA1_CTX), .blocksize = SHA1_BLOCK_LEN, .Init = SHA1Init_int, .Update = SHA1Update_int, .Final = SHA1Final_int, }; /* Authentication instances */ struct auth_hash auth_hash_hmac_sha1 = { .type = CRYPTO_SHA1_HMAC, .name = "HMAC-SHA1", .keysize = SHA1_BLOCK_LEN, .hashsize = SHA1_HASH_LEN, .ctxsize = sizeof(SHA1_CTX), .blocksize = SHA1_BLOCK_LEN, .Init = SHA1Init_int, .Update = SHA1Update_int, .Final = SHA1Final_int, }; /* * And now for auth. */ static void SHA1Init_int(void *ctx) { SHA1Init(ctx); } static int -SHA1Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +SHA1Update_int(void *ctx, const void *buf, u_int len) { SHA1Update(ctx, buf, len); return 0; } static void SHA1Final_int(u_int8_t *blk, void *ctx) { SHA1Final(blk, ctx); } Index: head/sys/opencrypto/xform_sha2.c =================================================================== --- head/sys/opencrypto/xform_sha2.c (revision 362027) +++ head/sys/opencrypto/xform_sha2.c (revision 362028) @@ -1,190 +1,190 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * AES XTS implementation in 2008 by Damien Miller * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * * Copyright (C) 2008, Damien Miller * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include -static int SHA224Update_int(void *, const u_int8_t *, u_int16_t); -static int SHA256Update_int(void *, const u_int8_t *, u_int16_t); -static int SHA384Update_int(void *, const u_int8_t *, u_int16_t); -static int SHA512Update_int(void *, const u_int8_t *, u_int16_t); +static int SHA224Update_int(void *, const void *, u_int); +static int SHA256Update_int(void *, const void *, u_int); +static int SHA384Update_int(void *, const void *, u_int); +static int SHA512Update_int(void *, const void *, u_int); /* Plain hashes */ struct auth_hash auth_hash_sha2_224 = { .type = CRYPTO_SHA2_224, .name = "SHA2-224", .hashsize = SHA2_224_HASH_LEN, .ctxsize = sizeof(SHA224_CTX), .blocksize = SHA2_224_BLOCK_LEN, .Init = (void (*)(void *)) SHA224_Init, .Update = SHA224Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA224_Final, }; struct auth_hash auth_hash_sha2_256 = { .type = CRYPTO_SHA2_256, .name = "SHA2-256", .keysize = SHA2_256_BLOCK_LEN, .hashsize = SHA2_256_HASH_LEN, .ctxsize = sizeof(SHA256_CTX), .blocksize = SHA2_256_BLOCK_LEN, .Init = (void (*)(void *)) SHA256_Init, .Update = SHA256Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA256_Final, }; struct auth_hash auth_hash_sha2_384 = { .type = CRYPTO_SHA2_384, .name = "SHA2-384", .keysize = SHA2_384_BLOCK_LEN, .hashsize = SHA2_384_HASH_LEN, .ctxsize = sizeof(SHA384_CTX), .blocksize = SHA2_384_BLOCK_LEN, .Init = (void (*)(void *)) SHA384_Init, .Update = SHA384Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA384_Final, }; struct auth_hash auth_hash_sha2_512 = { .type = CRYPTO_SHA2_512, .name = "SHA2-512", .keysize = SHA2_512_BLOCK_LEN, .hashsize = SHA2_512_HASH_LEN, .ctxsize = sizeof(SHA512_CTX), .blocksize = SHA2_512_BLOCK_LEN, .Init = (void (*)(void *)) SHA512_Init, .Update = SHA512Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA512_Final, }; /* Authentication instances */ struct auth_hash auth_hash_hmac_sha2_224 = { .type = CRYPTO_SHA2_224_HMAC, .name = "HMAC-SHA2-224", .keysize = SHA2_224_BLOCK_LEN, .hashsize = SHA2_224_HASH_LEN, .ctxsize = sizeof(SHA224_CTX), .blocksize = SHA2_224_BLOCK_LEN, .Init = (void (*)(void *)) SHA224_Init, .Update = SHA224Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA224_Final, }; struct auth_hash auth_hash_hmac_sha2_256 = { .type = CRYPTO_SHA2_256_HMAC, .name = "HMAC-SHA2-256", .keysize = SHA2_256_BLOCK_LEN, .hashsize = SHA2_256_HASH_LEN, .ctxsize = sizeof(SHA256_CTX), .blocksize = SHA2_256_BLOCK_LEN, .Init = (void (*)(void *)) SHA256_Init, .Update = SHA256Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA256_Final, }; struct auth_hash auth_hash_hmac_sha2_384 = { .type = CRYPTO_SHA2_384_HMAC, .name = "HMAC-SHA2-384", .keysize = SHA2_384_BLOCK_LEN, .hashsize = SHA2_384_HASH_LEN, .ctxsize = sizeof(SHA384_CTX), .blocksize = SHA2_384_BLOCK_LEN, .Init = (void (*)(void *)) SHA384_Init, .Update = SHA384Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA384_Final, }; struct auth_hash auth_hash_hmac_sha2_512 = { .type = CRYPTO_SHA2_512_HMAC, .name = "HMAC-SHA2-512", .keysize = SHA2_512_BLOCK_LEN, .hashsize = SHA2_512_HASH_LEN, .ctxsize = sizeof(SHA512_CTX), .blocksize = SHA2_512_BLOCK_LEN, .Init = (void (*)(void *)) SHA512_Init, .Update = SHA512Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA512_Final, }; /* * And now for auth. */ static int -SHA224Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +SHA224Update_int(void *ctx, const void *buf, u_int len) { SHA224_Update(ctx, buf, len); return 0; } static int -SHA256Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +SHA256Update_int(void *ctx, const void *buf, u_int len) { SHA256_Update(ctx, buf, len); return 0; } static int -SHA384Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +SHA384Update_int(void *ctx, const void *buf, u_int len) { SHA384_Update(ctx, buf, len); return 0; } static int -SHA512Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +SHA512Update_int(void *ctx, const void *buf, u_int len) { SHA512_Update(ctx, buf, len); return 0; }