FD.io VPP  v16.09
Vector Packet Processing
esp.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #if DPDK==1
16 #include <vnet/devices/dpdk/dpdk.h>
17 #endif
18 
19 #include <openssl/hmac.h>
20 #include <openssl/rand.h>
21 #include <openssl/evp.h>
22 
23 typedef struct
24 {
27  u8 data[0];
28 } esp_header_t;
29 
30 typedef struct
31 {
34 } esp_footer_t;
35 
36 /* *INDENT-OFF* */
37 typedef CLIB_PACKED (struct {
38  ip4_header_t ip4;
39  esp_header_t esp;
40 }) ip4_and_esp_header_t;
41 /* *INDENT-ON* */
42 
43 /* *INDENT-OFF* */
44 typedef CLIB_PACKED (struct {
45  ip6_header_t ip6;
46  esp_header_t esp;
47 }) ip6_and_esp_header_t;
48 /* *INDENT-ON* */
49 
50 typedef struct
51 {
52  const EVP_CIPHER *type;
54 
55 typedef struct
56 {
57  const EVP_MD *md;
60 
61 typedef struct
62 {
63  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
64  EVP_CIPHER_CTX encrypt_ctx;
65  CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
66  EVP_CIPHER_CTX decrypt_ctx;
67  CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
68  HMAC_CTX hmac_ctx;
73 
74 typedef struct
75 {
79 } esp_main_t;
80 
82 
83 always_inline void
85 {
86  esp_main_t *em = &esp_main;
88 
89  memset (em, 0, sizeof (em[0]));
90 
92  em->esp_crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_128].type = EVP_aes_128_cbc ();
93  em->esp_crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_192].type = EVP_aes_192_cbc ();
94  em->esp_crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_256].type = EVP_aes_256_cbc ();
95 
98 
99  i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA1_96];
100  i->md = EVP_sha1 ();
101  i->trunc_size = 12;
102 
103  i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA_256_96];
104  i->md = EVP_sha256 ();
105  i->trunc_size = 12;
106 
107  i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA_256_128];
108  i->md = EVP_sha256 ();
109  i->trunc_size = 16;
110 
111  i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA_384_192];
112  i->md = EVP_sha384 ();
113  i->trunc_size = 24;
114 
115  i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA_512_256];
116  i->md = EVP_sha512 ();
117  i->trunc_size = 32;
118 
121  int thread_id;
122 
123  for (thread_id = 0; thread_id < tm->n_vlib_mains - 1; thread_id++)
124  {
125  EVP_CIPHER_CTX_init (&(em->per_thread_data[thread_id].encrypt_ctx));
126  EVP_CIPHER_CTX_init (&(em->per_thread_data[thread_id].decrypt_ctx));
127  HMAC_CTX_init (&(em->per_thread_data[thread_id].hmac_ctx));
128  }
129 }
130 
131 always_inline unsigned int
133  u8 * key,
134  int key_len,
135  u8 * data, int data_len, u8 * signature, u8 use_esn, u32 seq_hi)
136 {
137  esp_main_t *em = &esp_main;
138  u32 cpu_index = os_get_cpu_number ();
139  HMAC_CTX *ctx = &(em->per_thread_data[cpu_index].hmac_ctx);
140  const EVP_MD *md = NULL;
141  unsigned int len;
142 
143  ASSERT (alg < IPSEC_INTEG_N_ALG);
144 
145  if (PREDICT_FALSE (em->esp_integ_algs[alg].md == 0))
146  return 0;
147 
148  if (PREDICT_FALSE (alg != em->per_thread_data[cpu_index].last_integ_alg))
149  {
150  md = em->esp_integ_algs[alg].md;
151  em->per_thread_data[cpu_index].last_integ_alg = alg;
152  }
153 
154  HMAC_Init (ctx, key, key_len, md);
155 
156  HMAC_Update (ctx, data, data_len);
157 
158  if (PREDICT_TRUE (use_esn))
159  HMAC_Update (ctx, (u8 *) & seq_hi, sizeof (seq_hi));
160  HMAC_Final (ctx, signature, &len);
161 
162  return em->esp_integ_algs[alg].trunc_size;
163 }
164 
165 
166 /*
167  * fd.io coding-style-patch-verification: ON
168  *
169  * Local Variables:
170  * eval: (c-set-style "gnu")
171  * End:
172  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
ipsec_crypto_alg_t last_decrypt_alg
Definition: esp.h:70
#define CLIB_CACHE_LINE_ALIGN_MARK(mark)
Definition: cache.h:68
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define PREDICT_TRUE(x)
Definition: clib.h:98
#define NULL
Definition: clib.h:55
static unsigned int hmac_calc(ipsec_integ_alg_t alg, u8 *key, int key_len, u8 *data, int data_len, u8 *signature, u8 use_esn, u32 seq_hi)
Definition: esp.h:132
ipsec_integ_alg_t last_integ_alg
Definition: esp.h:71
const EVP_CIPHER * type
Definition: esp.h:52
esp_crypto_alg_t * esp_crypto_algs
Definition: esp.h:76
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:407
esp_integ_alg_t * esp_integ_algs
Definition: esp.h:77
esp_main_t esp_main
Definition: esp.h:81
u8 trunc_size
Definition: esp.h:58
#define always_inline
Definition: clib.h:84
EVP_CIPHER_CTX encrypt_ctx
Definition: esp.h:64
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
#define PREDICT_FALSE(x)
Definition: clib.h:97
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
ipsec_crypto_alg_t
Definition: ipsec.h:41
static void esp_init()
Definition: esp.h:84
u32 seq
Definition: esp.h:26
u32 spi
Definition: esp.h:25
ipsec_crypto_alg_t last_encrypt_alg
Definition: esp.h:69
unsigned char u8
Definition: types.h:56
Definition: esp.h:74
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
typedef CLIB_PACKED(struct{ip4_header_t ip4;esp_header_t esp;}) ip4_and_esp_header_t
esp_main_per_thread_data_t * per_thread_data
Definition: esp.h:78
const EVP_MD * md
Definition: esp.h:57
EVP_CIPHER_CTX decrypt_ctx
Definition: esp.h:66
ipsec_integ_alg_t
Definition: ipsec.h:58