]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/mips/nlm/dev/sec/nlmseclib.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / mips / nlm / dev / sec / nlmseclib.c
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
59 static int
60 nlm_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
92 int
93 nlm_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
156 int
157 nlm_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
189 int
190 nlm_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
212 int
213 nlm_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
252 int
253 nlm_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 }
278 int
279 nlm_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 }