Home | History | Annotate | Line # | Download | only in x86
      1 /*	$OpenBSD: via.c,v 1.8 2006/11/17 07:47:56 tom Exp $	*/
      2 /*	$NetBSD: via_padlock.c,v 1.38 2026/04/29 16:29:59 kre Exp $ */
      3 
      4 /*-
      5  * Copyright (c) 2003 Jason Wright
      6  * Copyright (c) 2003, 2004 Theo de Raadt
      7  * All rights reserved.
      8  *
      9  * Permission to use, copy, modify, and distribute this software for any
     10  * purpose with or without fee is hereby granted, provided that the above
     11  * copyright notice and this permission notice appear in all copies.
     12  *
     13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     20  */
     21 
     22 #include <sys/cdefs.h>
     23 __KERNEL_RCSID(0, "$NetBSD: via_padlock.c,v 1.38 2026/04/29 16:29:59 kre Exp $");
     24 
     25 #include <sys/param.h>
     26 #include <sys/systm.h>
     27 #include <sys/signalvar.h>
     28 #include <sys/kernel.h>
     29 #include <sys/device.h>
     30 #include <sys/module.h>
     31 #include <sys/malloc.h>
     32 #include <sys/mbuf.h>
     33 #include <sys/cpu.h>
     34 
     35 #include <x86/specialreg.h>
     36 
     37 #include <machine/cpufunc.h>
     38 #include <machine/cpuvar.h>
     39 
     40 #include <crypto/aes/aes_keysched.h>
     41 
     42 #include <opencrypto/cryptodev.h>
     43 #include <opencrypto/cryptosoft.h>
     44 #include <opencrypto/xform.h>
     45 
     46 #include <opencrypto/cryptosoft_xform.c>
     47 
     48 #include <x86/via_padlock.h>
     49 
     50 static int	via_padlock_match(device_t, cfdata_t, void *);
     51 static void	via_padlock_attach(device_t, device_t, void *);
     52 static int	via_padlock_detach(device_t, int);
     53 static void	via_padlock_attach_intr(device_t);
     54 
     55 CFATTACH_DECL_NEW(
     56     padlock,
     57     sizeof(struct via_padlock_softc),
     58     via_padlock_match,
     59     via_padlock_attach,
     60     via_padlock_detach,
     61     NULL
     62 );
     63 
     64 int	via_padlock_crypto_newsession(void *, uint32_t *, struct cryptoini *);
     65 int	via_padlock_crypto_process(void *, struct cryptop *, int);
     66 int	via_padlock_crypto_swauth(struct cryptop *, struct cryptodesc *,
     67 	    struct swcr_data *, void *);
     68 int	via_padlock_crypto_encdec(struct cryptop *, struct cryptodesc *,
     69 	    struct via_padlock_session *, struct via_padlock_softc *, void *);
     70 void	via_padlock_crypto_freesession(void *, uint64_t);
     71 static	__inline void via_padlock_cbc(void *, void *, void *, void *, int,
     72 	    void *);
     73 
     74 static void
     75 via_c3_ace_init(struct via_padlock_softc *sc)
     76 {
     77 	/*
     78 	 * There is no reason to call into the kernel to use this
     79 	 * driver from userspace, because the crypto instructions can
     80 	 * be directly accessed there.  Setting CRYPTOCAP_F_SOFTWARE
     81 	 * has approximately the right semantics though the name is
     82 	 * confusing (however, consider that crypto via unprivileged
     83 	 * instructions _is_ "just software" in some sense).
     84 	 */
     85 	sc->sc_cid = crypto_get_driverid(CRYPTOCAP_F_SOFTWARE);
     86 	if (sc->sc_cid < 0) {
     87 		aprint_error_dev(sc->sc_dev,
     88 		    "could not get a crypto driver ID\n");
     89 		return;
     90 	}
     91 
     92 	sc->sc_cid_attached = true;
     93 
     94 	/*
     95 	 * Ask the opencrypto subsystem to register ourselves. Although
     96 	 * we don't support hardware offloading for various HMAC algorithms,
     97 	 * we will handle them, because opencrypto prefers drivers that
     98 	 * support all requested algorithms.
     99 	 *
    100 	 *
    101 	 * XXX We should actually implement the HMAC modes this hardware
    102 	 * XXX can accelerate (wrap its plain SHA1/SHA2 as HMAC) and
    103 	 * XXX strongly consider removing those passed through to cryptosoft.
    104 	 * XXX As it stands, we can "steal" sessions from drivers which could
    105 	 * XXX better accelerate them.
    106 	 *
    107 	 * XXX Note the ordering dependency between when this (or any
    108 	 * XXX crypto driver) attaches and when cryptosoft does.  We are
    109 	 * XXX basically counting on the swcrypto pseudo-device to just
    110 	 * XXX happen to attach last, or _it_ will steal every session
    111 	 * XXX from _us_!
    112 	 */
    113 #define REGISTER(alg) \
    114 	crypto_register(sc->sc_cid, alg, 0, 0, \
    115 	    via_padlock_crypto_newsession, via_padlock_crypto_freesession, \
    116 	    via_padlock_crypto_process, sc);
    117 
    118 	REGISTER(CRYPTO_AES_CBC);
    119 	REGISTER(CRYPTO_MD5_HMAC_96);
    120 	REGISTER(CRYPTO_MD5_HMAC);
    121 	REGISTER(CRYPTO_SHA1_HMAC_96);
    122 	REGISTER(CRYPTO_SHA1_HMAC);
    123 	REGISTER(CRYPTO_RIPEMD160_HMAC_96);
    124 	REGISTER(CRYPTO_RIPEMD160_HMAC);
    125 	REGISTER(CRYPTO_SHA2_HMAC);
    126 }
    127 
    128 int
    129 via_padlock_crypto_newsession(void *arg, uint32_t *sidp, struct cryptoini *cri)
    130 {
    131 	struct cryptoini *c;
    132 	struct via_padlock_softc *sc = arg;
    133 	struct via_padlock_session *ses = NULL;
    134 	const struct swcr_auth_hash *axf;
    135 	struct swcr_data *swd;
    136 	int sesn, cw0;
    137 	unsigned int i;
    138 
    139 	if (sc->sc_sessions == NULL) {
    140 		ses = sc->sc_sessions = malloc(sizeof(*ses), M_DEVBUF,
    141 		    M_NOWAIT);
    142 		if (ses == NULL)
    143 			return (ENOMEM);
    144 		sesn = 0;
    145 		sc->sc_nsessions = 1;
    146 	} else {
    147 		for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
    148 			if (sc->sc_sessions[sesn].ses_used == 0) {
    149 				ses = &sc->sc_sessions[sesn];
    150 				break;
    151 			}
    152 		}
    153 
    154 		if (ses == NULL) {
    155 			sesn = sc->sc_nsessions;
    156 			ses = malloc((sesn + 1) * sizeof(*ses), M_DEVBUF,
    157 			    M_NOWAIT);
    158 			if (ses == NULL)
    159 				return (ENOMEM);
    160 			memcpy(ses, sc->sc_sessions, sesn * sizeof(*ses));
    161 			memset(sc->sc_sessions, 0, sesn * sizeof(*ses));
    162 			free(sc->sc_sessions, M_DEVBUF);
    163 			sc->sc_sessions = ses;
    164 			ses = &sc->sc_sessions[sesn];
    165 			sc->sc_nsessions++;
    166 		}
    167 	}
    168 
    169 	memset(ses, 0, sizeof(*ses));
    170 	ses->ses_used = 1;
    171 
    172 	for (c = cri; c != NULL; c = c->cri_next) {
    173 		switch (c->cri_alg) {
    174 		case CRYPTO_AES_CBC:
    175 			memset(ses->ses_ekey, 0, sizeof(ses->ses_ekey));
    176 			memset(ses->ses_dkey, 0, sizeof(ses->ses_dkey));
    177 
    178 			switch (c->cri_klen) {
    179 			case 128:
    180 				/*
    181 				 * XXX Is this needed?  For AES-128 the
    182 				 * VIA padlock instructions usually
    183 				 * compute the key schedule internally.
    184 				 */
    185 				aes_keysched_enc(ses->ses_ekey,
    186 				    c->cri_key, 16);
    187 				aes_keysched_dec(ses->ses_dkey,
    188 				    c->cri_key, 16);
    189 				cw0 = C3_CRYPT_CWLO_KEY128;
    190 				break;
    191 			case 192:
    192 				aes_keysched_enc(ses->ses_ekey,
    193 				    c->cri_key, 24);
    194 				aes_keysched_dec(ses->ses_dkey,
    195 				    c->cri_key, 24);
    196 				cw0 = C3_CRYPT_CWLO_KEY192;
    197 				break;
    198 			case 256:
    199 				aes_keysched_enc(ses->ses_ekey,
    200 				    c->cri_key, 32);
    201 				aes_keysched_dec(ses->ses_dkey,
    202 				    c->cri_key, 32);
    203 				cw0 = C3_CRYPT_CWLO_KEY256;
    204 				break;
    205 			default:
    206 				return (EINVAL);
    207 			}
    208 			cw0 |= C3_CRYPT_CWLO_ALG_AES |
    209 				C3_CRYPT_CWLO_KEYGEN_SW |
    210 				C3_CRYPT_CWLO_NORMAL;
    211 
    212 			ses->ses_klen = c->cri_klen;
    213 			ses->ses_cw0 = cw0;
    214 
    215 			/* Convert words to host byte order (???) */
    216 			for (i = 0; i < 4*(AES_256_NROUNDS + 1); i++) {
    217 				ses->ses_ekey[i] = ntohl(ses->ses_ekey[i]);
    218 				ses->ses_dkey[i] = ntohl(ses->ses_dkey[i]);
    219 			}
    220 			break;
    221 
    222 		/* Use hashing implementations from the cryptosoft code. */
    223 		case CRYPTO_MD5_HMAC:
    224 			axf = &swcr_auth_hash_hmac_md5;
    225 			goto authcommon;
    226 		case CRYPTO_MD5_HMAC_96:
    227 			axf = &swcr_auth_hash_hmac_md5_96;
    228 			goto authcommon;
    229 		case CRYPTO_SHA1_HMAC:
    230 			axf = &swcr_auth_hash_hmac_sha1;
    231 			goto authcommon;
    232 		case CRYPTO_SHA1_HMAC_96:
    233 			axf = &swcr_auth_hash_hmac_sha1_96;
    234 			goto authcommon;
    235 		case CRYPTO_RIPEMD160_HMAC:
    236 			axf = &swcr_auth_hash_hmac_ripemd_160;
    237 			goto authcommon;
    238 		case CRYPTO_RIPEMD160_HMAC_96:
    239 			axf = &swcr_auth_hash_hmac_ripemd_160_96;
    240 			goto authcommon;
    241 		case CRYPTO_SHA2_HMAC:
    242 			if (cri->cri_klen == 256)
    243 				axf = &swcr_auth_hash_hmac_sha2_256;
    244 			else if (cri->cri_klen == 384)
    245 				axf = &swcr_auth_hash_hmac_sha2_384;
    246 			else if (cri->cri_klen == 512)
    247 				axf = &swcr_auth_hash_hmac_sha2_512;
    248 			else {
    249 				return EINVAL;
    250 			}
    251 		authcommon:
    252 			swd = malloc(sizeof(struct swcr_data), M_CRYPTO_DATA,
    253 			    M_NOWAIT|M_ZERO);
    254 			if (swd == NULL) {
    255 				via_padlock_crypto_freesession(sc, sesn);
    256 				return (ENOMEM);
    257 			}
    258 			ses->swd = swd;
    259 
    260 			swd->sw_ictx = malloc(axf->ctxsize,
    261 			    M_CRYPTO_DATA, M_NOWAIT);
    262 			if (swd->sw_ictx == NULL) {
    263 				via_padlock_crypto_freesession(sc, sesn);
    264 				return (ENOMEM);
    265 			}
    266 
    267 			swd->sw_octx = malloc(axf->ctxsize,
    268 			    M_CRYPTO_DATA, M_NOWAIT);
    269 			if (swd->sw_octx == NULL) {
    270 				via_padlock_crypto_freesession(sc, sesn);
    271 				return (ENOMEM);
    272 			}
    273 
    274 			for (i = 0; i < c->cri_klen / 8; i++)
    275 				c->cri_key[i] ^= HMAC_IPAD_VAL;
    276 
    277 			axf->Init(swd->sw_ictx);
    278 			axf->Update(swd->sw_ictx, c->cri_key, c->cri_klen / 8);
    279 			axf->Update(swd->sw_ictx, hmac_ipad_buffer,
    280 			    HMAC_BLOCK_LEN - (c->cri_klen / 8));
    281 
    282 			for (i = 0; i < c->cri_klen / 8; i++)
    283 				c->cri_key[i] ^= (HMAC_IPAD_VAL ^
    284 				    HMAC_OPAD_VAL);
    285 
    286 			axf->Init(swd->sw_octx);
    287 			axf->Update(swd->sw_octx, c->cri_key, c->cri_klen / 8);
    288 			axf->Update(swd->sw_octx, hmac_opad_buffer,
    289 			    HMAC_BLOCK_LEN - (c->cri_klen / 8));
    290 
    291 			for (i = 0; i < c->cri_klen / 8; i++)
    292 				c->cri_key[i] ^= HMAC_OPAD_VAL;
    293 
    294 			swd->sw_axf = axf;
    295 			swd->sw_alg = c->cri_alg;
    296 
    297 			break;
    298 		default:
    299 			return (EINVAL);
    300 		}
    301 	}
    302 
    303 	*sidp = VIAC3_SID(0, sesn);
    304 	return (0);
    305 }
    306 
    307 void
    308 via_padlock_crypto_freesession(void *arg, uint64_t tid)
    309 {
    310 	struct via_padlock_softc *sc = arg;
    311 	struct swcr_data *swd;
    312 	const struct swcr_auth_hash *axf;
    313 	int sesn;
    314 	uint32_t sid = ((uint32_t)tid) & 0xffffffff;
    315 
    316 	sesn = VIAC3_SESSION(sid);
    317 	KASSERTMSG(sesn >= 0, "sesn=%d", sesn);
    318 	KASSERTMSG(sesn < sc->sc_nsessions, "sesn=%d nsessions=%d",
    319 	    sesn, sc->sc_nsessions);
    320 
    321 	if (sc->sc_sessions[sesn].swd) {
    322 		swd = sc->sc_sessions[sesn].swd;
    323 		axf = swd->sw_axf;
    324 
    325 		if (swd->sw_ictx) {
    326 			memset(swd->sw_ictx, 0, axf->ctxsize);
    327 			free(swd->sw_ictx, M_CRYPTO_DATA);
    328 		}
    329 		if (swd->sw_octx) {
    330 			memset(swd->sw_octx, 0, axf->ctxsize);
    331 			free(swd->sw_octx, M_CRYPTO_DATA);
    332 		}
    333 		free(swd, M_CRYPTO_DATA);
    334 	}
    335 
    336 	memset(&sc->sc_sessions[sesn], 0, sizeof(sc->sc_sessions[sesn]));
    337 }
    338 
    339 static __inline void
    340 via_padlock_cbc(void *cw, void *src, void *dst, void *key, int rep,
    341     void *iv)
    342 {
    343 	unsigned int cr0;
    344 	int s;
    345 
    346 	s = splhigh();
    347 
    348 	cr0 = rcr0();		/* Permit access to SIMD/FPU path */
    349 	lcr0(cr0 & ~(CR0_EM|CR0_TS));
    350 
    351 	/* Do the deed */
    352 	__asm __volatile("pushf; popf");	/* force key reload */
    353 	__asm __volatile(".byte 0xf3, 0x0f, 0xa7, 0xd0" : /* rep xcrypt-cbc */
    354 			: "a" (iv), "b" (key), "c" (rep), "d" (cw), "S" (src), "D" (dst)
    355 			: "memory", "cc");
    356 
    357 	lcr0(cr0);
    358 
    359 	splx(s);
    360 }
    361 
    362 int
    363 via_padlock_crypto_swauth(struct cryptop *crp, struct cryptodesc *crd,
    364     struct swcr_data *sw, void *buf)
    365 {
    366 	int	type;
    367 
    368 	if (crp->crp_flags & CRYPTO_F_IMBUF)
    369 		type = CRYPTO_BUF_MBUF;
    370 	else
    371 		type= CRYPTO_BUF_IOV;
    372 
    373 	return (swcr_authcompute(crp, crd, sw, buf, type));
    374 }
    375 
    376 int
    377 via_padlock_crypto_encdec(struct cryptop *crp, struct cryptodesc *crd,
    378     struct via_padlock_session *ses, struct via_padlock_softc *sc, void *buf)
    379 {
    380 	uint32_t *key;
    381 
    382 	if ((crd->crd_len % 16) != 0)
    383 		return (EINVAL);
    384 
    385 	sc->op_buf = malloc(crd->crd_len, M_DEVBUF, M_NOWAIT);
    386 	if (sc->op_buf == NULL)
    387 		return (ENOMEM);
    388 
    389 	if (crd->crd_flags & CRD_F_ENCRYPT) {
    390 		sc->op_cw[0] = ses->ses_cw0 | C3_CRYPT_CWLO_ENCRYPT;
    391 		key = ses->ses_ekey;
    392 		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
    393 			memcpy(sc->op_iv, crd->crd_iv, 16);
    394 		else
    395 			cprng_fast(sc->op_iv, 16);
    396 
    397 		if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
    398 			if (crp->crp_flags & CRYPTO_F_IMBUF)
    399 				m_copyback((struct mbuf *)crp->crp_buf,
    400 				    crd->crd_inject, 16, sc->op_iv);
    401 			else if (crp->crp_flags & CRYPTO_F_IOV)
    402 				cuio_copyback((struct uio *)crp->crp_buf,
    403 				    crd->crd_inject, 16, sc->op_iv);
    404 			else
    405 				memcpy((char *)crp->crp_buf + crd->crd_inject,
    406 				    sc->op_iv, 16);
    407 		}
    408 	} else {
    409 		sc->op_cw[0] = ses->ses_cw0 | C3_CRYPT_CWLO_DECRYPT;
    410 		key = ses->ses_dkey;
    411 		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
    412 			memcpy(sc->op_iv, crd->crd_iv, 16);
    413 		else {
    414 			if (crp->crp_flags & CRYPTO_F_IMBUF)
    415 				m_copydata((struct mbuf *)crp->crp_buf,
    416 				    crd->crd_inject, 16, sc->op_iv);
    417 			else if (crp->crp_flags & CRYPTO_F_IOV)
    418 				cuio_copydata((struct uio *)crp->crp_buf,
    419 				    crd->crd_inject, 16, sc->op_iv);
    420 			else
    421 				memcpy(sc->op_iv, (char *)crp->crp_buf +
    422 				    crd->crd_inject, 16);
    423 		}
    424 	}
    425 
    426 	if (crp->crp_flags & CRYPTO_F_IMBUF)
    427 		m_copydata((struct mbuf *)crp->crp_buf,
    428 		    crd->crd_skip, crd->crd_len, sc->op_buf);
    429 	else if (crp->crp_flags & CRYPTO_F_IOV)
    430 		cuio_copydata((struct uio *)crp->crp_buf,
    431 		    crd->crd_skip, crd->crd_len, sc->op_buf);
    432 	else
    433 		memcpy(sc->op_buf, (char *)crp->crp_buf + crd->crd_skip,
    434 		    crd->crd_len);
    435 
    436 	sc->op_cw[1] = sc->op_cw[2] = sc->op_cw[3] = 0;
    437 	via_padlock_cbc(&sc->op_cw, sc->op_buf, sc->op_buf, key,
    438 	    crd->crd_len / 16, sc->op_iv);
    439 
    440 	if (crp->crp_flags & CRYPTO_F_IMBUF)
    441 		m_copyback((struct mbuf *)crp->crp_buf,
    442 		    crd->crd_skip, crd->crd_len, sc->op_buf);
    443 	else if (crp->crp_flags & CRYPTO_F_IOV)
    444 		cuio_copyback((struct uio *)crp->crp_buf,
    445 		    crd->crd_skip, crd->crd_len, sc->op_buf);
    446 	else
    447 		memcpy((char *)crp->crp_buf + crd->crd_skip, sc->op_buf,
    448 		    crd->crd_len);
    449 
    450 	if (sc->op_buf != NULL) {
    451 		memset(sc->op_buf, 0, crd->crd_len);
    452 		free(sc->op_buf, M_DEVBUF);
    453 		sc->op_buf = NULL;
    454 	}
    455 
    456 	return 0;
    457 }
    458 
    459 int
    460 via_padlock_crypto_process(void *arg, struct cryptop *crp, int hint)
    461 {
    462 	struct via_padlock_softc *sc = arg;
    463 	struct via_padlock_session *ses;
    464 	struct cryptodesc *crd;
    465 	int sesn, err = 0;
    466 
    467 	KASSERT(sc != NULL /*, ("via_padlock_crypto_process: null softc")*/);
    468 	if (crp == NULL || crp->crp_callback == NULL) {
    469 		err = EINVAL;
    470 		goto out;
    471 	}
    472 
    473 	sesn = VIAC3_SESSION(crp->crp_sid);
    474 	if (sesn >= sc->sc_nsessions) {
    475 		err = EINVAL;
    476 		goto out;
    477 	}
    478 	ses = &sc->sc_sessions[sesn];
    479 
    480 	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
    481 		switch (crd->crd_alg) {
    482 		case CRYPTO_AES_CBC:
    483 			if ((err = via_padlock_crypto_encdec(crp, crd, ses,
    484 			    sc, crp->crp_buf)) != 0)
    485 				goto out;
    486 			break;
    487 
    488 		case CRYPTO_MD5_HMAC:
    489 		case CRYPTO_SHA1_HMAC:
    490 		case CRYPTO_RIPEMD160_HMAC:
    491 		case CRYPTO_SHA2_HMAC:
    492 			if ((err = via_padlock_crypto_swauth(crp, crd,
    493 			    ses->swd, crp->crp_buf)) != 0)
    494 				goto out;
    495 			break;
    496 
    497 		default:
    498 			err = EINVAL;
    499 			goto out;
    500 		}
    501 	}
    502 out:
    503 	crp->crp_etype = err;
    504 	crypto_done(crp);
    505 	return 0;
    506 }
    507 
    508 static int
    509 via_padlock_match(device_t parent, cfdata_t cf, void *opaque)
    510 {
    511 	struct cpufeature_attach_args *cfaa = opaque;
    512 	struct cpu_info *ci = cfaa->ci;
    513 
    514 	if (strcmp(cfaa->name, "padlock") != 0)
    515 		return 0;
    516 	if ((cpu_feature[4] & (CPUID_VIA_HAS_ACE|CPUID_VIA_HAS_RNG)) == 0)
    517 		return 0;
    518 	if ((ci->ci_flags & (CPUF_BSP|CPUF_SP|CPUF_PRIMARY)) == 0)
    519 		return 0;
    520 	return 1;
    521 }
    522 
    523 static void
    524 via_padlock_attach(device_t parent, device_t self, void *opaque)
    525 {
    526 	struct via_padlock_softc *sc = device_private(self);
    527 
    528 	sc->sc_dev = self;
    529 
    530 	aprint_naive("\n");
    531 	aprint_normal(": VIA PadLock\n");
    532 
    533 	pmf_device_register(self, NULL, NULL);
    534 
    535 	config_interrupts(self, via_padlock_attach_intr);
    536 }
    537 
    538 static void
    539 via_padlock_attach_intr(device_t self)
    540 {
    541 	struct via_padlock_softc *sc = device_private(self);
    542 
    543 	aprint_normal("%s:", device_xname(self));
    544 	if (cpu_feature[4] & CPUID_VIA_HAS_RNG) {
    545 		aprint_normal(" RNG");
    546 	}
    547 	if (cpu_feature[4] & CPUID_VIA_HAS_ACE) {
    548 		via_c3_ace_init(sc);
    549 		aprint_normal(" ACE");
    550 	}
    551 	aprint_normal("\n");
    552 }
    553 
    554 static int
    555 via_padlock_detach(device_t self, int flags)
    556 {
    557 	struct via_padlock_softc *sc = device_private(self);
    558 
    559 	if (sc->sc_cid_attached) {
    560 		crypto_unregister(sc->sc_cid, CRYPTO_AES_CBC);
    561 		crypto_unregister(sc->sc_cid, CRYPTO_MD5_HMAC_96);
    562 		crypto_unregister(sc->sc_cid, CRYPTO_MD5_HMAC);
    563 		crypto_unregister(sc->sc_cid, CRYPTO_SHA1_HMAC_96);
    564 		crypto_unregister(sc->sc_cid, CRYPTO_SHA1_HMAC);
    565 		crypto_unregister(sc->sc_cid, CRYPTO_RIPEMD160_HMAC_96);
    566 		crypto_unregister(sc->sc_cid, CRYPTO_RIPEMD160_HMAC);
    567 		crypto_unregister(sc->sc_cid, CRYPTO_SHA2_HMAC);
    568 		sc->sc_cid_attached = false;
    569 	}
    570 
    571 	pmf_device_deregister(self);
    572 
    573 	return 0;
    574 }
    575 
    576 MODULE(MODULE_CLASS_DRIVER, padlock, NULL);
    577 
    578 #ifdef _MODULE
    579 #include "ioconf.c"
    580 #endif
    581 
    582 static int
    583 padlock_modcmd(modcmd_t cmd, void *opaque)
    584 {
    585 	int error = 0;
    586 
    587 	switch (cmd) {
    588 	case MODULE_CMD_INIT:
    589 #ifdef _MODULE
    590 		error = config_init_component(cfdriver_ioconf_padlock,
    591 		    cfattach_ioconf_padlock, cfdata_ioconf_padlock);
    592 #endif
    593 		return error;
    594 	case MODULE_CMD_FINI:
    595 #ifdef _MODULE
    596 		error = config_fini_component(cfdriver_ioconf_padlock,
    597 		    cfattach_ioconf_padlock, cfdata_ioconf_padlock);
    598 #endif
    599 		return error;
    600 	default:
    601 		return ENOTTY;
    602 	}
    603 }
    604