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