1/*- 2 * Copyright (c) 2003-2012 Broadcom Corporation 3 * All Rights Reserved 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD$"); 31 32#include <sys/param.h> 33#include <sys/types.h> 34#include <sys/systm.h> 35#include <sys/kernel.h> 36#include <sys/module.h> 37#include <sys/malloc.h> 38#include <sys/mbuf.h> 39#include <sys/lock.h> 40#include <sys/mutex.h> 41#include <sys/bus.h> 42#include <sys/uio.h> 43#include <machine/bus.h> 44#include <machine/md_var.h> 45#include <machine/cpuregs.h> 46 47#include <vm/vm.h> 48#include <vm/pmap.h> 49 50#include <opencrypto/cryptodev.h> 51 52#include <mips/nlm/hal/haldefs.h> 53#include <mips/nlm/hal/cop2.h> 54#include <mips/nlm/hal/fmn.h> 55#include <mips/nlm/hal/mips-extns.h> 56#include <mips/nlm/hal/nlmsaelib.h> 57#include <mips/nlm/dev/sec/nlmseclib.h> 58 59static int 60nlm_crypto_complete_sec_request(struct xlp_sec_softc *sc, 61 struct xlp_sec_command *cmd) 62{ 63 unsigned int fbvc; 64 struct nlm_fmn_msg m; 65 int ret; 66 67 fbvc = nlm_cpuid() / CMS_MAX_VCPU_VC; 68 m.msg[0] = m.msg[1] = m.msg[2] = m.msg[3] = 0; 69 70 m.msg[0] = nlm_crypto_form_pkt_fmn_entry0(fbvc, 0, 0, 71 cmd->ctrlp->cipherkeylen, vtophys(cmd->ctrlp)); 72 73 m.msg[1] = nlm_crypto_form_pkt_fmn_entry1(0, cmd->ctrlp->hashkeylen, 74 NLM_CRYPTO_PKT_DESC_SIZE(cmd->nsegs), vtophys(cmd->paramp)); 75 76 /* Software scratch pad */ 77 m.msg[2] = (uintptr_t)cmd; 78 sc->sec_msgsz = 3; 79 80 /* Send the message to sec/rsa engine vc */ 81 ret = nlm_fmn_msgsend(sc->sec_vc_start, sc->sec_msgsz, 82 FMN_SWCODE_CRYPTO, &m); 83 if (ret != 0) { 84#ifdef NLM_SEC_DEBUG 85 printf("%s: msgsnd failed (%x)\n", __func__, ret); 86#endif 87 return (ERESTART); 88 } 89 return (0); 90} 91 92int 93nlm_crypto_form_srcdst_segs(struct xlp_sec_command *cmd) 94{ 95 unsigned int srcseg = 0, dstseg = 0; 96 struct cryptodesc *cipdesc = NULL; 97 struct cryptop *crp = NULL; 98 99 crp = cmd->crp; 100 cipdesc = cmd->enccrd; 101 102 if (cipdesc != NULL) { 103 /* IV is given as ONE segment to avoid copy */ 104 if (cipdesc->crd_flags & CRD_F_IV_EXPLICIT) { 105 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg, 106 cmd->iv, cmd->ivlen); 107 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, dstseg, 108 cmd->iv, cmd->ivlen); 109 } 110 } 111 112 if (crp->crp_flags & CRYPTO_F_IMBUF) { 113 struct mbuf *m = NULL; 114 115 m = (struct mbuf *)crp->crp_buf; 116 while (m != NULL) { 117 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg, 118 mtod(m,caddr_t), m->m_len); 119 if (cipdesc != NULL) { 120 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, 121 dstseg, mtod(m,caddr_t), m->m_len); 122 } 123 m = m->m_next; 124 } 125 } else if (crp->crp_flags & CRYPTO_F_IOV) { 126 struct uio *uio = NULL; 127 struct iovec *iov = NULL; 128 int iol = 0; 129 130 uio = (struct uio *)crp->crp_buf; 131 iov = (struct iovec *)uio->uio_iov; 132 iol = uio->uio_iovcnt; 133 134 while (iol > 0) { 135 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg, 136 (caddr_t)iov->iov_base, iov->iov_len); 137 if (cipdesc != NULL) { 138 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, 139 dstseg, (caddr_t)iov->iov_base, 140 iov->iov_len); 141 } 142 iov++; 143 iol--; 144 } 145 } else { 146 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg, 147 ((caddr_t)crp->crp_buf), crp->crp_ilen); 148 if (cipdesc != NULL) { 149 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, dstseg, 150 ((caddr_t)crp->crp_buf), crp->crp_ilen); 151 } 152 } 153 return (0); 154} 155 156int 157nlm_crypto_do_cipher(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd) 158{ 159 struct cryptodesc *cipdesc = NULL; 160 unsigned char *cipkey = NULL; 161 int ret = 0; 162 163 cipdesc = cmd->enccrd; 164 cipkey = (unsigned char *)cipdesc->crd_key; 165 if (cmd->cipheralg == NLM_CIPHER_3DES) { 166 if (!(cipdesc->crd_flags & CRD_F_ENCRYPT)) { 167 uint64_t *k, *tkey; 168 k = (uint64_t *)cipdesc->crd_key; 169 tkey = (uint64_t *)cmd->des3key; 170 tkey[2] = k[0]; 171 tkey[1] = k[1]; 172 tkey[0] = k[2]; 173 cipkey = (unsigned char *)tkey; 174 } 175 } 176 nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, 0, NLM_HASH_BYPASS, 0, 177 cmd->cipheralg, cmd->ciphermode, cipkey, 178 (cipdesc->crd_klen >> 3), NULL, 0); 179 180 nlm_crypto_fill_cipher_pkt_param(cmd->ctrlp, cmd->paramp, 181 (cipdesc->crd_flags & CRD_F_ENCRYPT) ? 1 : 0, cmd->ivoff, 182 cmd->ivlen, cmd->cipheroff, cmd->cipherlen); 183 nlm_crypto_form_srcdst_segs(cmd); 184 185 ret = nlm_crypto_complete_sec_request(sc, cmd); 186 return (ret); 187} 188 189int 190nlm_crypto_do_digest(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd) 191{ 192 struct cryptodesc *digdesc = NULL; 193 int ret=0; 194 195 digdesc = cmd->maccrd; 196 197 nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, (digdesc->crd_klen) ? 1 : 0, 198 cmd->hashalg, cmd->hashmode, NLM_CIPHER_BYPASS, 0, 199 NULL, 0, digdesc->crd_key, digdesc->crd_klen >> 3); 200 201 nlm_crypto_fill_auth_pkt_param(cmd->ctrlp, cmd->paramp, 202 cmd->hashoff, cmd->hashlen, cmd->hmacpad, 203 (unsigned char *)cmd->hashdest); 204 205 nlm_crypto_form_srcdst_segs(cmd); 206 207 ret = nlm_crypto_complete_sec_request(sc, cmd); 208 209 return (ret); 210} 211 212int 213nlm_crypto_do_cipher_digest(struct xlp_sec_softc *sc, 214 struct xlp_sec_command *cmd) 215{ 216 struct cryptodesc *cipdesc=NULL, *digdesc=NULL; 217 unsigned char *cipkey = NULL; 218 int ret=0; 219 220 cipdesc = cmd->enccrd; 221 digdesc = cmd->maccrd; 222 223 cipkey = (unsigned char *)cipdesc->crd_key; 224 if (cmd->cipheralg == NLM_CIPHER_3DES) { 225 if (!(cipdesc->crd_flags & CRD_F_ENCRYPT)) { 226 uint64_t *k, *tkey; 227 k = (uint64_t *)cipdesc->crd_key; 228 tkey = (uint64_t *)cmd->des3key; 229 tkey[2] = k[0]; 230 tkey[1] = k[1]; 231 tkey[0] = k[2]; 232 cipkey = (unsigned char *)tkey; 233 } 234 } 235 nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, (digdesc->crd_klen) ? 1 : 0, 236 cmd->hashalg, cmd->hashmode, cmd->cipheralg, cmd->ciphermode, 237 cipkey, (cipdesc->crd_klen >> 3), 238 digdesc->crd_key, (digdesc->crd_klen >> 3)); 239 240 nlm_crypto_fill_cipher_auth_pkt_param(cmd->ctrlp, cmd->paramp, 241 (cipdesc->crd_flags & CRD_F_ENCRYPT) ? 1 : 0, cmd->hashsrc, 242 cmd->ivoff, cmd->ivlen, cmd->hashoff, cmd->hashlen, 243 cmd->hmacpad, cmd->cipheroff, cmd->cipherlen, 244 (unsigned char *)cmd->hashdest); 245 246 nlm_crypto_form_srcdst_segs(cmd); 247 248 ret = nlm_crypto_complete_sec_request(sc, cmd); 249 return (ret); 250} 251 252int 253nlm_get_digest_param(struct xlp_sec_command *cmd) 254{ 255 switch(cmd->maccrd->crd_alg) { 256 case CRYPTO_MD5: 257 cmd->hashalg = NLM_HASH_MD5; 258 cmd->hashmode = NLM_HASH_MODE_SHA1; 259 break; 260 case CRYPTO_SHA1: 261 cmd->hashalg = NLM_HASH_SHA; 262 cmd->hashmode = NLM_HASH_MODE_SHA1; 263 break; 264 case CRYPTO_MD5_HMAC: 265 cmd->hashalg = NLM_HASH_MD5; 266 cmd->hashmode = NLM_HASH_MODE_SHA1; 267 break; 268 case CRYPTO_SHA1_HMAC: 269 cmd->hashalg = NLM_HASH_SHA; 270 cmd->hashmode = NLM_HASH_MODE_SHA1; 271 break; 272 default: 273 /* Not supported */ 274 return (-1); 275 } 276 return (0); 277} 278int 279nlm_get_cipher_param(struct xlp_sec_command *cmd) 280{ 281 switch(cmd->enccrd->crd_alg) { 282 case CRYPTO_DES_CBC: 283 cmd->cipheralg = NLM_CIPHER_DES; 284 cmd->ciphermode = NLM_CIPHER_MODE_CBC; 285 cmd->ivlen = XLP_SEC_DES_IV_LENGTH; 286 break; 287 case CRYPTO_3DES_CBC: 288 cmd->cipheralg = NLM_CIPHER_3DES; 289 cmd->ciphermode = NLM_CIPHER_MODE_CBC; 290 cmd->ivlen = XLP_SEC_DES_IV_LENGTH; 291 break; 292 case CRYPTO_AES_CBC: 293 cmd->cipheralg = NLM_CIPHER_AES128; 294 cmd->ciphermode = NLM_CIPHER_MODE_CBC; 295 cmd->ivlen = XLP_SEC_AES_IV_LENGTH; 296 break; 297 case CRYPTO_ARC4: 298 cmd->cipheralg = NLM_CIPHER_ARC4; 299 cmd->ciphermode = NLM_CIPHER_MODE_ECB; 300 cmd->ivlen = XLP_SEC_ARC4_IV_LENGTH; 301 break; 302 default: 303 /* Not supported */ 304 return (-1); 305 } 306 return (0); 307} 308