xref: /freebsd/crypto/openssl/ssl/record/tls_pad.c (revision b077aed3)
1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery  * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery  */
9*b077aed3SPierre Pronchery 
10*b077aed3SPierre Pronchery #include <openssl/rand.h>
11*b077aed3SPierre Pronchery #include <openssl/evp.h>
12*b077aed3SPierre Pronchery #include "internal/constant_time.h"
13*b077aed3SPierre Pronchery #include "internal/cryptlib.h"
14*b077aed3SPierre Pronchery 
15*b077aed3SPierre Pronchery /*
16*b077aed3SPierre Pronchery  * This file has no dependencies on the rest of libssl because it is shared
17*b077aed3SPierre Pronchery  * with the providers. It contains functions for low level CBC TLS padding
18*b077aed3SPierre Pronchery  * removal. Responsibility for this lies with the cipher implementations in the
19*b077aed3SPierre Pronchery  * providers. However there are legacy code paths in libssl which also need to
20*b077aed3SPierre Pronchery  * do this. In time those legacy code paths can be removed and this file can be
21*b077aed3SPierre Pronchery  * moved out of libssl.
22*b077aed3SPierre Pronchery  */
23*b077aed3SPierre Pronchery 
24*b077aed3SPierre Pronchery static int ssl3_cbc_copy_mac(size_t *reclen,
25*b077aed3SPierre Pronchery                              size_t origreclen,
26*b077aed3SPierre Pronchery                              unsigned char *recdata,
27*b077aed3SPierre Pronchery                              unsigned char **mac,
28*b077aed3SPierre Pronchery                              int *alloced,
29*b077aed3SPierre Pronchery                              size_t block_size,
30*b077aed3SPierre Pronchery                              size_t mac_size,
31*b077aed3SPierre Pronchery                              size_t good,
32*b077aed3SPierre Pronchery                              OSSL_LIB_CTX *libctx);
33*b077aed3SPierre Pronchery 
34*b077aed3SPierre Pronchery int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
35*b077aed3SPierre Pronchery                                     size_t origreclen,
36*b077aed3SPierre Pronchery                                     unsigned char *recdata,
37*b077aed3SPierre Pronchery                                     unsigned char **mac,
38*b077aed3SPierre Pronchery                                     int *alloced,
39*b077aed3SPierre Pronchery                                     size_t block_size, size_t mac_size,
40*b077aed3SPierre Pronchery                                     OSSL_LIB_CTX *libctx);
41*b077aed3SPierre Pronchery 
42*b077aed3SPierre Pronchery int tls1_cbc_remove_padding_and_mac(size_t *reclen,
43*b077aed3SPierre Pronchery                                     size_t origreclen,
44*b077aed3SPierre Pronchery                                     unsigned char *recdata,
45*b077aed3SPierre Pronchery                                     unsigned char **mac,
46*b077aed3SPierre Pronchery                                     int *alloced,
47*b077aed3SPierre Pronchery                                     size_t block_size, size_t mac_size,
48*b077aed3SPierre Pronchery                                     int aead,
49*b077aed3SPierre Pronchery                                     OSSL_LIB_CTX *libctx);
50*b077aed3SPierre Pronchery 
51*b077aed3SPierre Pronchery /*-
52*b077aed3SPierre Pronchery  * ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
53*b077aed3SPierre Pronchery  * record in |recdata| by updating |reclen| in constant time. It also extracts
54*b077aed3SPierre Pronchery  * the MAC from the underlying record and places a pointer to it in |mac|. The
55*b077aed3SPierre Pronchery  * MAC data can either be newly allocated memory, or a pointer inside the
56*b077aed3SPierre Pronchery  * |recdata| buffer. If allocated then |*alloced| is set to 1, otherwise it is
57*b077aed3SPierre Pronchery  * set to 0.
58*b077aed3SPierre Pronchery  *
59*b077aed3SPierre Pronchery  * origreclen: the original record length before any changes were made
60*b077aed3SPierre Pronchery  * block_size: the block size of the cipher used to encrypt the record.
61*b077aed3SPierre Pronchery  * mac_size: the size of the MAC to be extracted
62*b077aed3SPierre Pronchery  * aead: 1 if an AEAD cipher is in use, or 0 otherwise
63*b077aed3SPierre Pronchery  * returns:
64*b077aed3SPierre Pronchery  *   0: if the record is publicly invalid.
65*b077aed3SPierre Pronchery  *   1: if the record is publicly valid. If the padding removal fails then the
66*b077aed3SPierre Pronchery  *      MAC returned is random.
67*b077aed3SPierre Pronchery  */
ssl3_cbc_remove_padding_and_mac(size_t * reclen,size_t origreclen,unsigned char * recdata,unsigned char ** mac,int * alloced,size_t block_size,size_t mac_size,OSSL_LIB_CTX * libctx)68*b077aed3SPierre Pronchery int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
69*b077aed3SPierre Pronchery                                     size_t origreclen,
70*b077aed3SPierre Pronchery                                     unsigned char *recdata,
71*b077aed3SPierre Pronchery                                     unsigned char **mac,
72*b077aed3SPierre Pronchery                                     int *alloced,
73*b077aed3SPierre Pronchery                                     size_t block_size, size_t mac_size,
74*b077aed3SPierre Pronchery                                     OSSL_LIB_CTX *libctx)
75*b077aed3SPierre Pronchery {
76*b077aed3SPierre Pronchery     size_t padding_length;
77*b077aed3SPierre Pronchery     size_t good;
78*b077aed3SPierre Pronchery     const size_t overhead = 1 /* padding length byte */  + mac_size;
79*b077aed3SPierre Pronchery 
80*b077aed3SPierre Pronchery     /*
81*b077aed3SPierre Pronchery      * These lengths are all public so we can test them in non-constant time.
82*b077aed3SPierre Pronchery      */
83*b077aed3SPierre Pronchery     if (overhead > *reclen)
84*b077aed3SPierre Pronchery         return 0;
85*b077aed3SPierre Pronchery 
86*b077aed3SPierre Pronchery     padding_length = recdata[*reclen - 1];
87*b077aed3SPierre Pronchery     good = constant_time_ge_s(*reclen, padding_length + overhead);
88*b077aed3SPierre Pronchery     /* SSLv3 requires that the padding is minimal. */
89*b077aed3SPierre Pronchery     good &= constant_time_ge_s(block_size, padding_length + 1);
90*b077aed3SPierre Pronchery     *reclen -= good & (padding_length + 1);
91*b077aed3SPierre Pronchery 
92*b077aed3SPierre Pronchery     return ssl3_cbc_copy_mac(reclen, origreclen, recdata, mac, alloced,
93*b077aed3SPierre Pronchery                              block_size, mac_size, good, libctx);
94*b077aed3SPierre Pronchery }
95*b077aed3SPierre Pronchery 
96*b077aed3SPierre Pronchery /*-
97*b077aed3SPierre Pronchery  * tls1_cbc_remove_padding_and_mac removes padding from the decrypted, TLS, CBC
98*b077aed3SPierre Pronchery  * record in |recdata| by updating |reclen| in constant time. It also extracts
99*b077aed3SPierre Pronchery  * the MAC from the underlying record and places a pointer to it in |mac|. The
100*b077aed3SPierre Pronchery  * MAC data can either be newly allocated memory, or a pointer inside the
101*b077aed3SPierre Pronchery  * |recdata| buffer. If allocated then |*alloced| is set to 1, otherwise it is
102*b077aed3SPierre Pronchery  * set to 0.
103*b077aed3SPierre Pronchery  *
104*b077aed3SPierre Pronchery  * origreclen: the original record length before any changes were made
105*b077aed3SPierre Pronchery  * block_size: the block size of the cipher used to encrypt the record.
106*b077aed3SPierre Pronchery  * mac_size: the size of the MAC to be extracted
107*b077aed3SPierre Pronchery  * aead: 1 if an AEAD cipher is in use, or 0 otherwise
108*b077aed3SPierre Pronchery  * returns:
109*b077aed3SPierre Pronchery  *   0: if the record is publicly invalid.
110*b077aed3SPierre Pronchery  *   1: if the record is publicly valid. If the padding removal fails then the
111*b077aed3SPierre Pronchery  *      MAC returned is random.
112*b077aed3SPierre Pronchery  */
tls1_cbc_remove_padding_and_mac(size_t * reclen,size_t origreclen,unsigned char * recdata,unsigned char ** mac,int * alloced,size_t block_size,size_t mac_size,int aead,OSSL_LIB_CTX * libctx)113*b077aed3SPierre Pronchery int tls1_cbc_remove_padding_and_mac(size_t *reclen,
114*b077aed3SPierre Pronchery                                     size_t origreclen,
115*b077aed3SPierre Pronchery                                     unsigned char *recdata,
116*b077aed3SPierre Pronchery                                     unsigned char **mac,
117*b077aed3SPierre Pronchery                                     int *alloced,
118*b077aed3SPierre Pronchery                                     size_t block_size, size_t mac_size,
119*b077aed3SPierre Pronchery                                     int aead,
120*b077aed3SPierre Pronchery                                     OSSL_LIB_CTX *libctx)
121*b077aed3SPierre Pronchery {
122*b077aed3SPierre Pronchery     size_t good = -1;
123*b077aed3SPierre Pronchery     size_t padding_length, to_check, i;
124*b077aed3SPierre Pronchery     size_t overhead = ((block_size == 1) ? 0 : 1) /* padding length byte */
125*b077aed3SPierre Pronchery                       + mac_size;
126*b077aed3SPierre Pronchery 
127*b077aed3SPierre Pronchery     /*
128*b077aed3SPierre Pronchery      * These lengths are all public so we can test them in non-constant
129*b077aed3SPierre Pronchery      * time.
130*b077aed3SPierre Pronchery      */
131*b077aed3SPierre Pronchery     if (overhead > *reclen)
132*b077aed3SPierre Pronchery         return 0;
133*b077aed3SPierre Pronchery 
134*b077aed3SPierre Pronchery     if (block_size != 1) {
135*b077aed3SPierre Pronchery 
136*b077aed3SPierre Pronchery         padding_length = recdata[*reclen - 1];
137*b077aed3SPierre Pronchery 
138*b077aed3SPierre Pronchery         if (aead) {
139*b077aed3SPierre Pronchery             /* padding is already verified and we don't need to check the MAC */
140*b077aed3SPierre Pronchery             *reclen -= padding_length + 1 + mac_size;
141*b077aed3SPierre Pronchery             return 1;
142*b077aed3SPierre Pronchery         }
143*b077aed3SPierre Pronchery 
144*b077aed3SPierre Pronchery         good = constant_time_ge_s(*reclen, overhead + padding_length);
145*b077aed3SPierre Pronchery         /*
146*b077aed3SPierre Pronchery          * The padding consists of a length byte at the end of the record and
147*b077aed3SPierre Pronchery          * then that many bytes of padding, all with the same value as the
148*b077aed3SPierre Pronchery          * length byte. Thus, with the length byte included, there are i+1 bytes
149*b077aed3SPierre Pronchery          * of padding. We can't check just |padding_length+1| bytes because that
150*b077aed3SPierre Pronchery          * leaks decrypted information. Therefore we always have to check the
151*b077aed3SPierre Pronchery          * maximum amount of padding possible. (Again, the length of the record
152*b077aed3SPierre Pronchery          * is public information so we can use it.)
153*b077aed3SPierre Pronchery          */
154*b077aed3SPierre Pronchery         to_check = 256;        /* maximum amount of padding, inc length byte. */
155*b077aed3SPierre Pronchery         if (to_check > *reclen)
156*b077aed3SPierre Pronchery             to_check = *reclen;
157*b077aed3SPierre Pronchery 
158*b077aed3SPierre Pronchery         for (i = 0; i < to_check; i++) {
159*b077aed3SPierre Pronchery             unsigned char mask = constant_time_ge_8_s(padding_length, i);
160*b077aed3SPierre Pronchery             unsigned char b = recdata[*reclen - 1 - i];
161*b077aed3SPierre Pronchery             /*
162*b077aed3SPierre Pronchery              * The final |padding_length+1| bytes should all have the value
163*b077aed3SPierre Pronchery              * |padding_length|. Therefore the XOR should be zero.
164*b077aed3SPierre Pronchery              */
165*b077aed3SPierre Pronchery             good &= ~(mask & (padding_length ^ b));
166*b077aed3SPierre Pronchery         }
167*b077aed3SPierre Pronchery 
168*b077aed3SPierre Pronchery         /*
169*b077aed3SPierre Pronchery          * If any of the final |padding_length+1| bytes had the wrong value, one
170*b077aed3SPierre Pronchery          * or more of the lower eight bits of |good| will be cleared.
171*b077aed3SPierre Pronchery          */
172*b077aed3SPierre Pronchery         good = constant_time_eq_s(0xff, good & 0xff);
173*b077aed3SPierre Pronchery         *reclen -= good & (padding_length + 1);
174*b077aed3SPierre Pronchery     }
175*b077aed3SPierre Pronchery 
176*b077aed3SPierre Pronchery     return ssl3_cbc_copy_mac(reclen, origreclen, recdata, mac, alloced,
177*b077aed3SPierre Pronchery                              block_size, mac_size, good, libctx);
178*b077aed3SPierre Pronchery }
179*b077aed3SPierre Pronchery 
180*b077aed3SPierre Pronchery /*-
181*b077aed3SPierre Pronchery  * ssl3_cbc_copy_mac copies |md_size| bytes from the end of the record in
182*b077aed3SPierre Pronchery  * |recdata| to |*mac| in constant time (independent of the concrete value of
183*b077aed3SPierre Pronchery  * the record length |reclen|, which may vary within a 256-byte window).
184*b077aed3SPierre Pronchery  *
185*b077aed3SPierre Pronchery  * On entry:
186*b077aed3SPierre Pronchery  *   origreclen >= mac_size
187*b077aed3SPierre Pronchery  *   mac_size <= EVP_MAX_MD_SIZE
188*b077aed3SPierre Pronchery  *
189*b077aed3SPierre Pronchery  * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with
190*b077aed3SPierre Pronchery  * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into
191*b077aed3SPierre Pronchery  * a single or pair of cache-lines, then the variable memory accesses don't
192*b077aed3SPierre Pronchery  * actually affect the timing. CPUs with smaller cache-lines [if any] are
193*b077aed3SPierre Pronchery  * not multi-core and are not considered vulnerable to cache-timing attacks.
194*b077aed3SPierre Pronchery  */
195*b077aed3SPierre Pronchery #define CBC_MAC_ROTATE_IN_PLACE
196*b077aed3SPierre Pronchery 
ssl3_cbc_copy_mac(size_t * reclen,size_t origreclen,unsigned char * recdata,unsigned char ** mac,int * alloced,size_t block_size,size_t mac_size,size_t good,OSSL_LIB_CTX * libctx)197*b077aed3SPierre Pronchery static int ssl3_cbc_copy_mac(size_t *reclen,
198*b077aed3SPierre Pronchery                              size_t origreclen,
199*b077aed3SPierre Pronchery                              unsigned char *recdata,
200*b077aed3SPierre Pronchery                              unsigned char **mac,
201*b077aed3SPierre Pronchery                              int *alloced,
202*b077aed3SPierre Pronchery                              size_t block_size,
203*b077aed3SPierre Pronchery                              size_t mac_size,
204*b077aed3SPierre Pronchery                              size_t good,
205*b077aed3SPierre Pronchery                              OSSL_LIB_CTX *libctx)
206*b077aed3SPierre Pronchery {
207*b077aed3SPierre Pronchery #if defined(CBC_MAC_ROTATE_IN_PLACE)
208*b077aed3SPierre Pronchery     unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
209*b077aed3SPierre Pronchery     unsigned char *rotated_mac;
210*b077aed3SPierre Pronchery     char aux1, aux2, aux3, mask;
211*b077aed3SPierre Pronchery #else
212*b077aed3SPierre Pronchery     unsigned char rotated_mac[EVP_MAX_MD_SIZE];
213*b077aed3SPierre Pronchery #endif
214*b077aed3SPierre Pronchery     unsigned char randmac[EVP_MAX_MD_SIZE];
215*b077aed3SPierre Pronchery     unsigned char *out;
216*b077aed3SPierre Pronchery 
217*b077aed3SPierre Pronchery     /*
218*b077aed3SPierre Pronchery      * mac_end is the index of |recdata| just after the end of the MAC.
219*b077aed3SPierre Pronchery      */
220*b077aed3SPierre Pronchery     size_t mac_end = *reclen;
221*b077aed3SPierre Pronchery     size_t mac_start = mac_end - mac_size;
222*b077aed3SPierre Pronchery     size_t in_mac;
223*b077aed3SPierre Pronchery     /*
224*b077aed3SPierre Pronchery      * scan_start contains the number of bytes that we can ignore because the
225*b077aed3SPierre Pronchery      * MAC's position can only vary by 255 bytes.
226*b077aed3SPierre Pronchery      */
227*b077aed3SPierre Pronchery     size_t scan_start = 0;
228*b077aed3SPierre Pronchery     size_t i, j;
229*b077aed3SPierre Pronchery     size_t rotate_offset;
230*b077aed3SPierre Pronchery 
231*b077aed3SPierre Pronchery     if (!ossl_assert(origreclen >= mac_size
232*b077aed3SPierre Pronchery                      && mac_size <= EVP_MAX_MD_SIZE))
233*b077aed3SPierre Pronchery         return 0;
234*b077aed3SPierre Pronchery 
235*b077aed3SPierre Pronchery     /* If no MAC then nothing to be done */
236*b077aed3SPierre Pronchery     if (mac_size == 0) {
237*b077aed3SPierre Pronchery         /* No MAC so we can do this in non-constant time */
238*b077aed3SPierre Pronchery         if (good == 0)
239*b077aed3SPierre Pronchery             return 0;
240*b077aed3SPierre Pronchery         return 1;
241*b077aed3SPierre Pronchery     }
242*b077aed3SPierre Pronchery 
243*b077aed3SPierre Pronchery     *reclen -= mac_size;
244*b077aed3SPierre Pronchery 
245*b077aed3SPierre Pronchery     if (block_size == 1) {
246*b077aed3SPierre Pronchery         /* There's no padding so the position of the MAC is fixed */
247*b077aed3SPierre Pronchery         if (mac != NULL)
248*b077aed3SPierre Pronchery             *mac = &recdata[*reclen];
249*b077aed3SPierre Pronchery         if (alloced != NULL)
250*b077aed3SPierre Pronchery             *alloced = 0;
251*b077aed3SPierre Pronchery         return 1;
252*b077aed3SPierre Pronchery     }
253*b077aed3SPierre Pronchery 
254*b077aed3SPierre Pronchery     /* Create the random MAC we will emit if padding is bad */
255*b077aed3SPierre Pronchery     if (RAND_bytes_ex(libctx, randmac, mac_size, 0) <= 0)
256*b077aed3SPierre Pronchery         return 0;
257*b077aed3SPierre Pronchery 
258*b077aed3SPierre Pronchery     if (!ossl_assert(mac != NULL && alloced != NULL))
259*b077aed3SPierre Pronchery         return 0;
260*b077aed3SPierre Pronchery     *mac = out = OPENSSL_malloc(mac_size);
261*b077aed3SPierre Pronchery     if (*mac == NULL)
262*b077aed3SPierre Pronchery         return 0;
263*b077aed3SPierre Pronchery     *alloced = 1;
264*b077aed3SPierre Pronchery 
265*b077aed3SPierre Pronchery #if defined(CBC_MAC_ROTATE_IN_PLACE)
266*b077aed3SPierre Pronchery     rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
267*b077aed3SPierre Pronchery #endif
268*b077aed3SPierre Pronchery 
269*b077aed3SPierre Pronchery     /* This information is public so it's safe to branch based on it. */
270*b077aed3SPierre Pronchery     if (origreclen > mac_size + 255 + 1)
271*b077aed3SPierre Pronchery         scan_start = origreclen - (mac_size + 255 + 1);
272*b077aed3SPierre Pronchery 
273*b077aed3SPierre Pronchery     in_mac = 0;
274*b077aed3SPierre Pronchery     rotate_offset = 0;
275*b077aed3SPierre Pronchery     memset(rotated_mac, 0, mac_size);
276*b077aed3SPierre Pronchery     for (i = scan_start, j = 0; i < origreclen; i++) {
277*b077aed3SPierre Pronchery         size_t mac_started = constant_time_eq_s(i, mac_start);
278*b077aed3SPierre Pronchery         size_t mac_ended = constant_time_lt_s(i, mac_end);
279*b077aed3SPierre Pronchery         unsigned char b = recdata[i];
280*b077aed3SPierre Pronchery 
281*b077aed3SPierre Pronchery         in_mac |= mac_started;
282*b077aed3SPierre Pronchery         in_mac &= mac_ended;
283*b077aed3SPierre Pronchery         rotate_offset |= j & mac_started;
284*b077aed3SPierre Pronchery         rotated_mac[j++] |= b & in_mac;
285*b077aed3SPierre Pronchery         j &= constant_time_lt_s(j, mac_size);
286*b077aed3SPierre Pronchery     }
287*b077aed3SPierre Pronchery 
288*b077aed3SPierre Pronchery     /* Now rotate the MAC */
289*b077aed3SPierre Pronchery #if defined(CBC_MAC_ROTATE_IN_PLACE)
290*b077aed3SPierre Pronchery     j = 0;
291*b077aed3SPierre Pronchery     for (i = 0; i < mac_size; i++) {
292*b077aed3SPierre Pronchery         /*
293*b077aed3SPierre Pronchery          * in case cache-line is 32 bytes,
294*b077aed3SPierre Pronchery          * load from both lines and select appropriately
295*b077aed3SPierre Pronchery          */
296*b077aed3SPierre Pronchery         aux1 = rotated_mac[rotate_offset & ~32];
297*b077aed3SPierre Pronchery         aux2 = rotated_mac[rotate_offset | 32];
298*b077aed3SPierre Pronchery         mask = constant_time_eq_8(rotate_offset & ~32, rotate_offset);
299*b077aed3SPierre Pronchery         aux3 = constant_time_select_8(mask, aux1, aux2);
300*b077aed3SPierre Pronchery         rotate_offset++;
301*b077aed3SPierre Pronchery 
302*b077aed3SPierre Pronchery         /* If the padding wasn't good we emit a random MAC */
303*b077aed3SPierre Pronchery         out[j++] = constant_time_select_8((unsigned char)(good & 0xff),
304*b077aed3SPierre Pronchery                                           aux3,
305*b077aed3SPierre Pronchery                                           randmac[i]);
306*b077aed3SPierre Pronchery         rotate_offset &= constant_time_lt_s(rotate_offset, mac_size);
307*b077aed3SPierre Pronchery     }
308*b077aed3SPierre Pronchery #else
309*b077aed3SPierre Pronchery     memset(out, 0, mac_size);
310*b077aed3SPierre Pronchery     rotate_offset = mac_size - rotate_offset;
311*b077aed3SPierre Pronchery     rotate_offset &= constant_time_lt_s(rotate_offset, mac_size);
312*b077aed3SPierre Pronchery     for (i = 0; i < mac_size; i++) {
313*b077aed3SPierre Pronchery         for (j = 0; j < mac_size; j++)
314*b077aed3SPierre Pronchery             out[j] |= rotated_mac[i] & constant_time_eq_8_s(j, rotate_offset);
315*b077aed3SPierre Pronchery         rotate_offset++;
316*b077aed3SPierre Pronchery         rotate_offset &= constant_time_lt_s(rotate_offset, mac_size);
317*b077aed3SPierre Pronchery 
318*b077aed3SPierre Pronchery         /* If the padding wasn't good we emit a random MAC */
319*b077aed3SPierre Pronchery         out[i] = constant_time_select_8((unsigned char)(good & 0xff), out[i],
320*b077aed3SPierre Pronchery                                         randmac[i]);
321*b077aed3SPierre Pronchery     }
322*b077aed3SPierre Pronchery #endif
323*b077aed3SPierre Pronchery 
324*b077aed3SPierre Pronchery     return 1;
325*b077aed3SPierre Pronchery }
326