Coverage Report

Created: 2026-08-15 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/src/ssl_sk.c
Line
Count
Source
1
/* ssl_sk.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
#if !defined(WOLFSSL_SSL_SK_INCLUDED)
25
    #ifndef WOLFSSL_IGNORE_FILE_WARN
26
        #warning ssl_sk.c does not need to be compiled separately from ssl.c
27
    #endif
28
#else
29
30
/* In OpenSSL, OPENSSL_STACK is structure with an array of data pointers.
31
 *
32
 * In wolfSSL, WOLFSSL_STACK is a linked-list of nodes and therefore the first
33
 * node has no data but the type is set.
34
 * When the first data is set, the first node has the data stored against it and
35
 * the number of nodes goes up to 1.
36
 * If a new node is prepended then, to keep the pointer the same, the first
37
 * node is copied into a new node and inserted after first node, and the new
38
 * data is put into the first node.
39
 */
40
41
/*******************************************************************************
42
 * SK node APIs
43
 ******************************************************************************/
44
45
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
46
    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
47
    defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
48
/* Creates a generic wolfSSL stack node.
49
 *
50
 * @param [in] heap  eap hint for dynamic memory allocation.
51
 * @return  WOLFSSL_STACK structure on success.
52
 * @return  NULL when dynamic memory allocation fails.
53
 */
54
WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap)
55
38.2k
{
56
38.2k
    WOLFSSL_STACK* node;
57
58
38.2k
    WOLFSSL_ENTER("wolfSSL_sk_new_node");
59
60
38.2k
    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap,
61
38.2k
        DYNAMIC_TYPE_OPENSSL);
62
38.2k
    if (node != NULL) {
63
38.2k
        XMEMSET(node, 0, sizeof(*node));
64
38.2k
        node->heap = heap;
65
38.2k
    }
66
67
38.2k
    return node;
68
38.2k
}
69
#endif
70
71
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
72
    defined(OPENSSL_ALL)
73
/* Disposes of WOLFSSL_STACK object.
74
 *
75
 * Cannot use node after this call.
76
 *
77
 * @param [in] node  WOLFSSL_STACK object.
78
 */
79
void wolfSSL_sk_free_node(WOLFSSL_STACK* node)
80
37.9k
{
81
    /* Don't dereference node for heap when NULL. */
82
37.9k
    if (node != NULL) {
83
37.9k
        XFREE(node, node->heap, DYNAMIC_TYPE_OPENSSL);
84
37.9k
    }
85
37.9k
}
86
#endif
87
88
#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
89
/* Gets the node from stack at the index.
90
 *
91
 * @param [in] stack  Stack of nodes.
92
 * @param [in] idx    Index of node to get.
93
 * @return  Node at index on success.
94
 * @return  NULL when no node at index.
95
 */
96
WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* stack, int idx)
97
0
{
98
0
    int i;
99
0
    WOLFSSL_STACK* ret;
100
101
0
    if ((idx < 0) || (idx > (int)stack->num)) {
102
0
        ret = NULL;
103
0
    }
104
0
    else {
105
0
        ret = stack;
106
0
        for (i = 0; i < idx; i++) {
107
0
            ret = ret->next;
108
0
        }
109
0
    }
110
111
0
    return ret;
112
0
}
113
#endif /* !NO_CERT && OPENSSL_EXTRA*/
114
115
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
116
117
#ifndef NO_CERTS
118
/* Get data pointer from node.
119
 *
120
 * @param [in] node       Node to get data from.
121
 * @param [in] no_static  Don't return static data.
122
 * @return  Data pointer of node on success.
123
 * @return  NULL when node type is STACK_TYPE_CIPHER.
124
 */
125
static void* wolfssl_sk_node_get_data(WOLFSSL_STACK* node, int no_static)
126
0
{
127
0
    void *ret = NULL;
128
129
0
    switch (node->type) {
130
0
        case STACK_TYPE_CIPHER:
131
0
            if (!no_static) {
132
0
                ret = &node->data.cipher;
133
0
            }
134
0
            break;
135
0
        case STACK_TYPE_X509:
136
0
        case STACK_TYPE_GEN_NAME:
137
0
        case STACK_TYPE_BIO:
138
0
        case STACK_TYPE_OBJ:
139
0
        case STACK_TYPE_STRING:
140
0
        case STACK_TYPE_ACCESS_DESCRIPTION:
141
0
        case STACK_TYPE_X509_EXT:
142
0
        case STACK_TYPE_X509_REQ_ATTR:
143
0
        case STACK_TYPE_NULL:
144
0
        case STACK_TYPE_X509_NAME:
145
0
        case STACK_TYPE_X509_NAME_ENTRY:
146
0
        case STACK_TYPE_CONF_VALUE:
147
0
        case STACK_TYPE_X509_INFO:
148
0
        case STACK_TYPE_BY_DIR_entry:
149
0
        case STACK_TYPE_BY_DIR_hash:
150
0
        case STACK_TYPE_X509_OBJ:
151
0
        case STACK_TYPE_DIST_POINT:
152
0
        case STACK_TYPE_X509_CRL:
153
0
        case STACK_TYPE_X509_REVOKED:
154
0
        case STACK_TYPE_GENERAL_SUBTREE:
155
0
        default:
156
0
            ret = node->data.generic;
157
0
            break;
158
0
    }
159
160
0
    return ret;
161
0
}
162
163
/* Set data with type into node.
164
 *
165
 * @param [in, out] node  Node to place data into.
166
 * @param [in]      type  Type of data.
167
 * @param [in]      data  Data to set.
168
 */
169
static void wolfssl_sk_node_set_data(WOLFSSL_STACK* node, WOLF_STACK_TYPE type,
170
    const void* data)
171
37.9k
{
172
37.9k
    switch (type) {
173
0
        case STACK_TYPE_CIPHER:
174
0
            node->data.cipher = *(WOLFSSL_CIPHER*)data;
175
0
#ifdef OPENSSL_ALL
176
0
            if (node->hash_fn != NULL)
177
0
                node->hash = node->hash_fn(&node->data.cipher);
178
0
#endif
179
0
            break;
180
0
        case STACK_TYPE_X509:
181
0
        case STACK_TYPE_GEN_NAME:
182
0
        case STACK_TYPE_BIO:
183
0
        case STACK_TYPE_OBJ:
184
0
        case STACK_TYPE_STRING:
185
0
        case STACK_TYPE_ACCESS_DESCRIPTION:
186
0
        case STACK_TYPE_X509_EXT:
187
0
        case STACK_TYPE_X509_REQ_ATTR:
188
0
        case STACK_TYPE_NULL:
189
37.9k
        case STACK_TYPE_X509_NAME:
190
37.9k
        case STACK_TYPE_X509_NAME_ENTRY:
191
37.9k
        case STACK_TYPE_CONF_VALUE:
192
37.9k
        case STACK_TYPE_X509_INFO:
193
37.9k
        case STACK_TYPE_BY_DIR_entry:
194
37.9k
        case STACK_TYPE_BY_DIR_hash:
195
37.9k
        case STACK_TYPE_X509_OBJ:
196
37.9k
        case STACK_TYPE_DIST_POINT:
197
37.9k
        case STACK_TYPE_X509_CRL:
198
37.9k
        case STACK_TYPE_X509_REVOKED:
199
37.9k
        case STACK_TYPE_GENERAL_SUBTREE:
200
37.9k
        default:
201
37.9k
            node->data.generic = (void*)data;
202
37.9k
#ifdef OPENSSL_ALL
203
37.9k
            if (node->hash_fn != NULL)
204
0
                node->hash = node->hash_fn(node->data.generic);
205
37.9k
#endif
206
37.9k
            break;
207
37.9k
    }
208
37.9k
}
209
210
/* Pushes the node onto the stack.
211
 *
212
 * stack will point to node on success.
213
 *
214
 * @param [in, out] stack  Stack of nodes.
215
 * @param [in]      node   Node to push on.
216
 *
217
 * @return WOLFSSL_SUCCESS on success
218
 * @return WOLFSSL_FAILURE when stack or node is NULL.
219
 */
220
int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* node)
221
0
{
222
0
    int ret = WOLFSSL_SUCCESS;
223
224
    /* Validate parameters. */
225
0
    if (stack == NULL || node == NULL) {
226
0
        ret = WOLFSSL_FAILURE;
227
0
    }
228
0
    if (ret == WOLFSSL_SUCCESS) {
229
0
        if (*stack == NULL) {
230
            /* First node. */
231
0
            node->num = 1;
232
0
        }
233
0
        else {
234
            /* Place new node at start of the stack. */
235
0
            node->num  = (*stack)->num + 1;
236
0
            node->next = *stack;
237
0
        }
238
        /* Return new start. */
239
0
        *stack = node;
240
0
    }
241
242
0
    return ret;
243
0
}
244
245
/* Pushes the node onto the back of the stack.
246
 *
247
 * If *stack is NULL, node becomes the head.
248
 *
249
 * @param [in, out] stack  Stack of nodes.
250
 * @param [in]      node   Node to append.
251
 *
252
 * @return WOLFSSL_SUCCESS on success
253
 * @return WOLFSSL_FAILURE when stack or node is NULL.
254
 */
255
int wolfSSL_sk_push_back_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* node)
256
0
{
257
0
    int ret = WOLFSSL_SUCCESS;
258
259
    /* Validate parameters. */
260
0
    if (stack == NULL || node == NULL) {
261
0
        ret = WOLFSSL_FAILURE;
262
0
    }
263
0
    if (ret == WOLFSSL_SUCCESS) {
264
0
        node->next = NULL;
265
        /* Tail node has num of 1, indicating 1 node till the end */
266
0
        node->num = 1;
267
268
0
        if (*stack == NULL) {
269
            /* First node. */
270
0
            *stack = node;
271
0
        }
272
0
        else {
273
            /* Walk to the end and append.  Each node's num field holds the
274
             * count of nodes from that node to the tail (inclusive), so
275
             * every existing node's num increases by one. */
276
0
            WOLFSSL_STACK* cur = *stack;
277
0
            while (cur->next != NULL) {
278
0
                cur->num++;
279
0
                cur = cur->next;
280
0
            }
281
0
            cur->num++;
282
0
            cur->next = node;
283
0
        }
284
0
    }
285
286
0
    return ret;
287
0
}
288
289
/* Removes the node at the index from the stack and returns data.
290
 *
291
 * This is an internal API.
292
 *
293
 * @param [in, out] stack  Stack of nodes.
294
 * @param [in]      idx    Index of node to remove.
295
 * @return  Data in node on success.
296
 * @return  NULL when no node at index or no data.
297
 */
298
void* wolfSSL_sk_pop_node(WOLFSSL_STACK* stack, int idx)
299
0
{
300
0
    void* ret = NULL;
301
0
    WOLFSSL_STACK* tmp = NULL;
302
0
    WOLFSSL_STACK* prev;
303
304
    /* Validate parameters. */
305
0
    if ((stack != NULL) && (stack->num != 0)) {
306
0
        stack->num--;
307
        /* Popping first node handled differently. */
308
0
        if (idx == 0 || stack->next == NULL) {
309
0
            ret = wolfssl_sk_node_get_data(stack, 1);
310
            /* Clear out data if we are returning it. */
311
0
            if (ret != NULL) {
312
0
                stack->data.generic = NULL;
313
0
            }
314
0
            if (stack->next) {
315
                /* Keep the first node as it is the pointer passed in. */
316
0
                tmp = stack->next;
317
0
                XMEMCPY(stack, stack->next, sizeof(WOLFSSL_STACK));
318
0
                wolfSSL_sk_free_node(tmp);
319
0
            }
320
0
        }
321
0
        else {
322
            /* Find node at index and take out it. */
323
0
            prev = stack;
324
0
            tmp = stack->next;
325
0
            while ((--idx != 0) && (tmp->next != NULL)) {
326
0
                prev = tmp;
327
0
                prev->num--;
328
0
                tmp = tmp->next;
329
0
            }
330
0
            prev->next = tmp->next;
331
332
            /* Get data to return and free node only. */
333
0
            ret = wolfssl_sk_node_get_data(tmp, 1);
334
0
            wolfSSL_sk_free_node(tmp);
335
0
        }
336
0
    }
337
338
0
    return ret;
339
0
}
340
#endif /* NO_CERTS */
341
#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
342
343
/*******************************************************************************
344
 * SK APIs
345
 ******************************************************************************/
346
347
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
348
    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
349
    defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
350
/* Creates a new stack of the requested type.
351
 *
352
 * This is an internal API.
353
 *
354
 * @param [in] type  Type of stack.
355
 * @return  Empty stack on success.
356
 * @return  NULL when dynamic memory allocation fails.
357
 */
358
WOLFSSL_STACK* wolfssl_sk_new_type(WOLF_STACK_TYPE type)
359
0
{
360
0
    return wolfssl_sk_new_type_ex(type, NULL);
361
0
}
362
363
WOLFSSL_STACK* wolfssl_sk_new_type_ex(WOLF_STACK_TYPE type, void* heap)
364
0
{
365
0
    WOLFSSL_STACK* stack = wolfSSL_sk_new_node(heap);
366
0
    if (stack != NULL) {
367
0
        stack->type = type;
368
0
    }
369
0
    return stack;
370
0
}
371
#endif
372
373
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
374
/* Creates a new NULL type stack.
375
 *
376
 * This is an internal API.
377
 *
378
 * @return  Empty stack on success.
379
 * @return  NULL when dynamic memory allocation fails.
380
 */
381
WOLFSSL_STACK* wolfSSL_sk_new_null(void)
382
0
{
383
0
    WOLFSSL_ENTER("wolfSSL_sk_new_null");
384
385
0
    return wolfssl_sk_new_type(STACK_TYPE_NULL);
386
0
}
387
388
/* Duplicate the data of a node into another.
389
 *
390
 * Limited too: STACK_TYPE_X509, STACK_TYPE_CIPHER, STACK_TYPE_GEN_NAME,
391
 *              STACK_TYPE_OBJ, STACK_TYPE_X509_OBJ.
392
 *
393
 * @param [in, out] dst  Destination node.
394
 * @param [in]      src  Source node.
395
 * @return  0 on success.
396
 * @return  1 when duplication failed or stack type is not supported.
397
 */
398
static int wolfssl_sk_dup_data(WOLFSSL_STACK* dst, WOLFSSL_STACK* src)
399
0
{
400
0
    int err = 0;
401
402
0
    switch (src->type) {
403
0
        case STACK_TYPE_X509:
404
0
            if (src->data.x509 == NULL) {
405
0
                break;
406
0
            }
407
0
            dst->data.x509 = wolfSSL_X509_dup(src->data.x509);
408
0
            if (dst->data.x509 == NULL) {
409
0
                WOLFSSL_MSG("wolfSSL_X509_dup error");
410
0
                err = 1;
411
0
                break;
412
0
            }
413
0
            break;
414
0
        case STACK_TYPE_CIPHER:
415
0
            wolfSSL_CIPHER_copy(&src->data.cipher, &dst->data.cipher);
416
0
            break;
417
0
        case STACK_TYPE_GEN_NAME:
418
0
            if (src->data.gn == NULL) {
419
0
                break;
420
0
            }
421
0
            dst->data.gn = wolfSSL_GENERAL_NAME_dup(src->data.gn);
422
0
            if (dst->data.gn == NULL) {
423
0
                WOLFSSL_MSG("wolfSSL_GENERAL_NAME_new error");
424
0
                err = 1;
425
0
                break;
426
0
            }
427
0
            break;
428
0
        case STACK_TYPE_OBJ:
429
0
            if (src->data.obj == NULL) {
430
0
                break;
431
0
            }
432
0
            dst->data.obj = wolfSSL_ASN1_OBJECT_dup(src->data.obj);
433
0
            if (dst->data.obj == NULL) {
434
0
                WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_dup error");
435
0
                err = 1;
436
0
                break;
437
0
            }
438
0
            break;
439
0
        case STACK_TYPE_X509_CRL:
440
#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
441
            if (src->data.crl == NULL) {
442
                break;
443
            }
444
            dst->data.crl = wolfSSL_X509_CRL_dup(src->data.crl);
445
            if (dst->data.crl == NULL) {
446
                WOLFSSL_MSG("wolfSSL_X509_CRL_dup error");
447
                err = 1;
448
                break;
449
            }
450
#else
451
0
            WOLFSSL_MSG("CRL support not enabled");
452
0
            err = 1;
453
0
#endif
454
0
            break;
455
0
        case STACK_TYPE_X509_OBJ:
456
0
#if defined(OPENSSL_ALL)
457
0
            if (src->data.x509_obj == NULL) {
458
0
                break;
459
0
            }
460
0
            dst->data.x509_obj = wolfSSL_X509_OBJECT_dup(
461
0
                src->data.x509_obj);
462
0
            if (dst->data.x509_obj == NULL) {
463
0
                WOLFSSL_MSG("wolfSSL_X509_OBJECT_dup error");
464
0
                err = 1;
465
0
                break;
466
0
            }
467
#else
468
            WOLFSSL_MSG("OPENSSL_ALL support not enabled");
469
            err = 1;
470
#endif
471
0
            break;
472
0
        case STACK_TYPE_BIO:
473
0
        case STACK_TYPE_STRING:
474
0
        case STACK_TYPE_ACCESS_DESCRIPTION:
475
0
        case STACK_TYPE_X509_EXT:
476
0
        case STACK_TYPE_X509_REQ_ATTR:
477
0
        case STACK_TYPE_NULL:
478
0
        case STACK_TYPE_X509_NAME:
479
0
        case STACK_TYPE_X509_NAME_ENTRY:
480
0
        case STACK_TYPE_CONF_VALUE:
481
0
        case STACK_TYPE_X509_INFO:
482
0
        case STACK_TYPE_BY_DIR_entry:
483
0
        case STACK_TYPE_BY_DIR_hash:
484
0
        case STACK_TYPE_DIST_POINT:
485
0
        case STACK_TYPE_X509_REVOKED:
486
0
        case STACK_TYPE_GENERAL_SUBTREE:
487
0
        default:
488
0
            WOLFSSL_MSG("Unsupported stack type");
489
0
            err = 1;
490
0
            break;
491
0
    }
492
493
0
    return err;
494
0
}
495
496
/* Duplicate the stack of nodes.
497
 *
498
 * OpenSSL does a shallow copy but we map to wolfSSL_shallow_sk_dup()
499
 * when we want a shallow copy.
500
 *
501
 * Data is copied/duplicated - deep copy.
502
 *
503
 * Limited too: STACK_TYPE_X509, STACK_TYPE_CIPHER, STACK_TYPE_GEN_NAME,
504
 *              STACK_TYPE_OBJ, STACK_TYPE_X509_OBJ.
505
 *
506
 * @param [in, out] stack  Stack of nodes.
507
 * @return  A new stack of nodes with data duplicated/copied on success.
508
 * @return  NULL on error.
509
 */
510
WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* stack)
511
0
{
512
0
    WOLFSSL_STACK* ret = NULL;
513
0
    WOLFSSL_STACK* last = NULL;
514
0
    int err = 0;
515
516
0
    WOLFSSL_ENTER("wolfSSL_sk_dup");
517
518
0
    for (; stack != NULL; stack = stack->next) {
519
        /* New node for duplicate stack. */
520
0
        WOLFSSL_STACK* cur = wolfSSL_sk_new_node(stack->heap);
521
0
        if (cur == NULL) {
522
0
            WOLFSSL_MSG("wolfSSL_sk_new_node error");
523
0
            err = 1;
524
0
            break;
525
0
        }
526
527
0
        if (ret == NULL) {
528
            /* Keep the first node for returning. */
529
0
            ret = cur;
530
0
        }
531
0
        if (last != NULL) {
532
            /* Add new node to end of list. */
533
0
            last->next = cur;
534
0
        }
535
        /* Update last node in linked list. */
536
0
        last = cur;
537
538
0
        XMEMCPY(cur, stack, sizeof(WOLFSSL_STACK));
539
        /* We will allocate new memory for this */
540
0
        XMEMSET(&cur->data, 0, sizeof(cur->data));
541
0
        cur->next = NULL;
542
543
0
        err = wolfssl_sk_dup_data(cur, stack);
544
0
        if (err) {
545
0
            break;
546
0
        }
547
0
    }
548
549
0
    if (err && (ret != NULL)) {
550
0
        wolfSSL_sk_pop_free(ret, NULL);
551
0
        ret = NULL;
552
0
    }
553
554
0
    return ret;
555
0
}
556
557
/* Shallow duplicate a stack of nodes.
558
 *
559
 * @param [in] stack  Stack of nodes.
560
 * @return  A new stack of nodes with data duplicated/copied on success.
561
 * @return  NULL on error.
562
 */
563
WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* stack)
564
0
{
565
566
0
    WOLFSSL_STACK* ret = NULL;
567
0
    WOLFSSL_STACK** prev = &ret;
568
569
0
    WOLFSSL_ENTER("wolfSSL_shallow_sk_dup");
570
571
0
    for (; stack != NULL; stack = stack->next) {
572
0
        WOLFSSL_STACK* cur = wolfSSL_sk_new_node(stack->heap);
573
0
        if (cur == NULL) {
574
0
            WOLFSSL_MSG("wolfSSL_sk_new_node error");
575
0
            wolfSSL_sk_free(ret);
576
0
            ret = NULL;
577
0
            break;
578
0
        }
579
580
0
        XMEMCPY(cur, stack, sizeof(WOLFSSL_STACK));
581
0
        cur->next = NULL;
582
583
0
        *prev = cur;
584
0
        prev = &cur->next;
585
0
    }
586
587
0
    return ret;
588
0
}
589
#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
590
591
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
592
    defined(OPENSSL_ALL)
593
/* Free the nodes in the stack only.
594
 *
595
 * @param [in] stack  Stack of nodes.
596
 */
597
void wolfSSL_sk_free(WOLFSSL_STACK* stack)
598
98.1k
{
599
98.1k
    WOLFSSL_ENTER("wolfSSL_sk_free");
600
601
136k
    while (stack != NULL) {
602
37.9k
        WOLFSSL_STACK* next = stack->next;
603
37.9k
        wolfSSL_sk_free_node(stack);
604
37.9k
        stack = next;
605
37.9k
    }
606
98.1k
}
607
#endif
608
609
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
610
    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_ALL)
611
/* Get the number of nodes in the stack.
612
 *
613
 * @param [in] stack  Stack of nodes.
614
 * @return  Number of nodes in stack on success.
615
 * @return  0 when no nodes or stack is NULL.
616
 */
617
int wolfSSL_sk_num(const WOLFSSL_STACK* stack)
618
0
{
619
0
    int num = 0;
620
621
0
    WOLFSSL_ENTER("wolfSSL_sk_num");
622
623
0
    if (stack != NULL) {
624
0
        num = (int)stack->num;
625
0
    }
626
627
0
    return num;
628
0
}
629
630
/* Get the value/data in a node from the stack at the index.
631
 *
632
 * If stack type is STACK_TYPE_CONF_VALUE and OPENSSL_EXTRA is not defined,
633
 * the value will be NULL.
634
 *
635
 * @param [in] stack  Stack of nodes.
636
 * @param [in] i      Index of node to get value/data.
637
 * @return  Data in node at index on success.
638
 * @return  NULL when no node at index.
639
 */
640
void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i)
641
0
{
642
0
    void* val;
643
644
0
    WOLFSSL_ENTER("wolfSSL_sk_value");
645
646
0
    for (; (sk != NULL) && (i > 0); i--) {
647
0
        sk = sk->next;
648
0
    }
649
650
0
    if (sk == NULL) {
651
0
        val = NULL;
652
0
    }
653
0
    else {
654
0
        switch (sk->type) {
655
0
            case STACK_TYPE_CIPHER:
656
0
                val = (void*)&sk->data.cipher;
657
0
                break;
658
0
            case STACK_TYPE_CONF_VALUE:
659
        #ifndef OPENSSL_EXTRA
660
                val = NULL;
661
                break;
662
        #endif
663
0
            case STACK_TYPE_X509:
664
0
            case STACK_TYPE_GEN_NAME:
665
0
            case STACK_TYPE_BIO:
666
0
            case STACK_TYPE_OBJ:
667
0
            case STACK_TYPE_STRING:
668
0
            case STACK_TYPE_ACCESS_DESCRIPTION:
669
0
            case STACK_TYPE_X509_EXT:
670
0
            case STACK_TYPE_X509_REQ_ATTR:
671
0
            case STACK_TYPE_NULL:
672
0
            case STACK_TYPE_X509_NAME:
673
0
            case STACK_TYPE_X509_NAME_ENTRY:
674
0
            case STACK_TYPE_X509_INFO:
675
0
            case STACK_TYPE_BY_DIR_entry:
676
0
            case STACK_TYPE_BY_DIR_hash:
677
0
            case STACK_TYPE_X509_OBJ:
678
0
            case STACK_TYPE_DIST_POINT:
679
0
            case STACK_TYPE_X509_CRL:
680
0
            case STACK_TYPE_X509_REVOKED:
681
0
            case STACK_TYPE_GENERAL_SUBTREE:
682
0
            default:
683
0
                val = sk->data.generic;
684
0
                break;
685
0
        }
686
0
    }
687
688
0
    return val;
689
0
}
690
#endif
691
692
#if (!defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \
693
     defined(WOLFSSL_WPAS_SMALL))) || defined(WOLFSSL_QT) || \
694
     defined(OPENSSL_ALL)
695
/* Put the data into a node at the end of the list.
696
 *
697
 * @param [in, out] stack  Stack of objects.
698
 * @param [in]      data   Data to store in stack.
699
 * @return  Number of nodes in stack on success.
700
 * @return  WOLFSSL_FAILURE when data is NULL.
701
 * @return  WOLFSSL_FATAL_ERROR when stack is NULL.
702
 */
703
int wolfSSL_sk_push(WOLFSSL_STACK* stack, const void *data)
704
37.9k
{
705
37.9k
    WOLFSSL_ENTER("wolfSSL_sk_push");
706
707
37.9k
    return wolfSSL_sk_insert(stack, data, -1);
708
37.9k
}
709
710
/* Put the data into a node at an index in the list.
711
 *
712
 * @param [in, out] stack  Stack of objects.
713
 * @param [in]      data   Data to store in stack.
714
 * @return  Number of nodes in stack on success.
715
 * @return  WOLFSSL_FAILURE when data is NULL.
716
 * @return  WOLFSSL_FATAL_ERROR when stack is NULL.
717
 */
718
int wolfSSL_sk_insert(WOLFSSL_STACK *stack, const void *data, int idx)
719
37.9k
{
720
37.9k
    int ret;
721
37.9k
    WOLFSSL_STACK* node;
722
37.9k
    WOLFSSL_ENTER("wolfSSL_sk_insert");
723
724
    /* Validate parameters. */
725
37.9k
    if (stack == NULL) {
726
0
        ret = WOLFSSL_FATAL_ERROR;
727
0
    }
728
37.9k
    else if (data == NULL) {
729
0
        ret = WOLFSSL_FAILURE;
730
0
    }
731
37.9k
    else if (stack->num == 0) {
732
        /* No data set in stack - set data into empty first node. */
733
12.1k
        wolfssl_sk_node_set_data(stack, stack->type, data);
734
12.1k
        stack->num = 1;
735
12.1k
        ret = 1;
736
12.1k
    }
737
25.8k
    else {
738
        /* Create a new node. */
739
25.8k
        node = wolfSSL_sk_new_node(stack->heap);
740
25.8k
        if (node == NULL) {
741
1
            WOLFSSL_MSG("Memory error");
742
1
            ret = WOLFSSL_FAILURE;
743
1
        }
744
25.8k
        else {
745
            /* Place at front of linked-list. */
746
25.8k
            if (idx == 0) {
747
                /* Special case where we need to change the values in the head
748
                 * element to avoid changing the initial pointer. */
749
0
                XMEMCPY(node, stack, sizeof(WOLFSSL_STACK));
750
0
                wolfssl_sk_node_set_data(stack, stack->type, data);
751
0
                stack->num++;
752
0
                stack->next = node;
753
0
            }
754
            /* Place new node with data into list. */
755
25.8k
            else {
756
25.8k
                WOLFSSL_STACK* prev;
757
25.8k
                unsigned long num = stack->num;
758
759
25.8k
                node->type    = stack->type;
760
25.8k
            #ifdef OPENSSL_ALL
761
25.8k
                node->hash_fn = stack->hash_fn;
762
25.8k
            #endif
763
                /* Put data into new node. */
764
25.8k
                wolfssl_sk_node_set_data(node, stack->type, data);
765
766
                /* Update count as new node being placed after first. */
767
25.8k
                stack->num++;
768
25.8k
                prev = stack;
769
72.0k
                while (((--idx) != 0) && (prev->next != NULL)) {
770
46.2k
                    prev = prev->next;
771
                    /* Update count as new node being placed after this one. */
772
46.2k
                    prev->num = num--;
773
46.2k
                }
774
                /* Set count for new node. */
775
25.8k
                node->num = num;
776
                /* Place node in linked list after prev. */
777
25.8k
                node->next = prev->next;
778
25.8k
                prev->next = node;
779
25.8k
            }
780
781
            /* Returning new stack count. */
782
25.8k
            ret = (int)stack->num;
783
25.8k
        }
784
25.8k
    }
785
786
37.9k
    return ret;
787
37.9k
}
788
#endif
789
790
#if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \
791
    defined(WOLFSSL_WPAS_SMALL))
792
/* Remove the top node from the stack and return its data.
793
 *
794
 * @param [in, out] stack  Stack of nodes with data.
795
 * @return  Data in top node on success.
796
 * @return  NULL when stack is NULL or stack is empty.
797
 */
798
void* wolfSSL_sk_pop(WOLFSSL_STACK* stack)
799
0
{
800
0
    WOLFSSL_ENTER("wolfSSL_sk_pop");
801
802
0
    return wolfSSL_sk_pop_node(stack, -1);
803
0
}
804
805
#endif /* !NO_CERTS && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */
806
807
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
808
/* Pop off data from the stack. Checks that the type matches the stack type.
809
 *
810
 * This is an internal API.
811
 *
812
 * @param [in, out] stack  Stack of data.
813
 * @param [in]      type   Type of stack.
814
 * @return  Data on success.
815
 * @return  NULL when stack is NULL or no nodes left in stack.
816
 */
817
void* wolfssl_sk_pop_type(WOLFSSL_STACK* stack, WOLF_STACK_TYPE type)
818
0
{
819
0
    void* data = NULL;
820
821
    /* Check we have a stack passed in of the right type. */
822
0
    if ((stack != NULL) && (stack->type == type))
823
0
        data = wolfSSL_sk_pop(stack);
824
825
0
    return data;
826
0
}
827
#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
828
829
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
830
    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_ALL)
831
/* Get the free function for the stack type.
832
 *
833
 * @param [in] type  Type of stack object.
834
 * @return  A free function on success.
835
 * @return  NULL when no free function to use.
836
 */
837
static wolfSSL_sk_freefunc wolfssl_sk_get_free_func(WOLF_STACK_TYPE type)
838
298
{
839
298
    wolfSSL_sk_freefunc func = NULL;
840
841
298
    switch(type) {
842
0
       case STACK_TYPE_ACCESS_DESCRIPTION:
843
0
        #if defined(OPENSSL_ALL)
844
0
            func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free;
845
0
        #endif
846
0
            break;
847
0
        case STACK_TYPE_X509:
848
0
            func = (wolfSSL_sk_freefunc)wolfSSL_X509_free;
849
0
            break;
850
0
        case STACK_TYPE_X509_OBJ:
851
0
        #ifdef OPENSSL_ALL
852
0
            func = (wolfSSL_sk_freefunc)wolfSSL_X509_OBJECT_free;
853
0
        #endif
854
0
            break;
855
0
        case STACK_TYPE_OBJ:
856
0
            func = (wolfSSL_sk_freefunc)wolfSSL_ASN1_OBJECT_free;
857
0
            break;
858
0
        case STACK_TYPE_DIST_POINT:
859
0
        #ifdef OPENSSL_EXTRA
860
0
            func = (wolfSSL_sk_freefunc)wolfSSL_DIST_POINT_free;
861
0
        #endif
862
0
            break;
863
0
        case STACK_TYPE_GEN_NAME:
864
0
            func = (wolfSSL_sk_freefunc)wolfSSL_GENERAL_NAME_free;
865
0
            break;
866
0
        case STACK_TYPE_GENERAL_SUBTREE:
867
0
        #if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS)
868
0
            func = (wolfSSL_sk_freefunc)wolfSSL_GENERAL_SUBTREE_free;
869
0
        #endif
870
0
            break;
871
0
        case STACK_TYPE_STRING:
872
0
        #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
873
0
            defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
874
0
            func = (wolfSSL_sk_freefunc)wolfSSL_WOLFSSL_STRING_free;
875
0
        #endif
876
0
            break;
877
298
        case STACK_TYPE_X509_NAME:
878
298
        #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
879
298
            && !defined(WOLFCRYPT_ONLY)
880
298
            func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_free;
881
298
        #endif
882
298
            break;
883
0
        case STACK_TYPE_X509_NAME_ENTRY:
884
0
        #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
885
0
            && !defined(WOLFCRYPT_ONLY)
886
0
            func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_ENTRY_free;
887
0
        #endif
888
0
            break;
889
0
        case STACK_TYPE_X509_EXT:
890
0
        #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
891
0
            func = (wolfSSL_sk_freefunc)wolfSSL_X509_EXTENSION_free;
892
0
        #endif
893
0
            break;
894
0
        case STACK_TYPE_X509_REQ_ATTR:
895
        #if defined(OPENSSL_ALL) && \
896
            (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ))
897
            func = (wolfSSL_sk_freefunc)wolfSSL_X509_ATTRIBUTE_free;
898
        #endif
899
0
            break;
900
0
        case STACK_TYPE_CONF_VALUE:
901
0
        #if defined(OPENSSL_ALL)
902
0
            func = (wolfSSL_sk_freefunc)wolfSSL_X509V3_conf_free;
903
0
        #endif
904
0
            break;
905
0
        case STACK_TYPE_X509_INFO:
906
0
        #if defined(OPENSSL_ALL)
907
0
            func = (wolfSSL_sk_freefunc)wolfSSL_X509_INFO_free;
908
0
        #endif
909
0
            break;
910
0
        case STACK_TYPE_BIO:
911
0
        #if !defined(NO_BIO) && defined(OPENSSL_EXTRA)
912
0
            func = (wolfSSL_sk_freefunc)wolfSSL_BIO_vfree;
913
0
        #endif
914
0
            break;
915
0
        case STACK_TYPE_BY_DIR_entry:
916
0
        #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && \
917
0
            !defined(NO_WOLFSSL_DIR)
918
0
            func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_entry_free;
919
0
        #endif
920
0
            break;
921
0
        case STACK_TYPE_BY_DIR_hash:
922
0
        #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && \
923
0
            !defined(NO_WOLFSSL_DIR)
924
0
            func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_HASH_free;
925
0
        #endif
926
0
            break;
927
0
        case STACK_TYPE_X509_CRL:
928
        #if defined(HAVE_CRL) && (defined(OPENSSL_EXTRA) || \
929
            defined(WOLFSSL_WPAS_SMALL))
930
            func = (wolfSSL_sk_freefunc)wolfSSL_X509_CRL_free;
931
        #endif
932
0
            break;
933
0
        case STACK_TYPE_X509_REVOKED:
934
        #if defined(HAVE_CRL) && defined(OPENSSL_EXTRA)
935
            func = (wolfSSL_sk_freefunc)wolfSSL_X509_REVOKED_free;
936
        #endif
937
0
            break;
938
0
        case STACK_TYPE_CIPHER:
939
            /* Static copy kept in node. */
940
0
        case STACK_TYPE_NULL:
941
0
        default:
942
0
            break;
943
298
    }
944
945
298
    return func;
946
298
}
947
948
/* Free all nodes and the dynamic data associated with them.
949
 *
950
 * This is an internal API.
951
 *
952
 * @param [in, out] sk    Stack of objects.
953
 * @param [in]      func  Function to use to free objects.
954
 */
955
void wolfSSL_sk_pop_free(WOLFSSL_STACK* stack, wolfSSL_sk_freefunc func)
956
516k
{
957
516k
    WOLFSSL_ENTER("wolfSSL_sk_pop_free");
958
959
    /* Validate parameters. */
960
516k
    if (stack == NULL) {
961
        /* pop_free can be called with NULL, do not print bad argument */
962
515k
        return;
963
515k
    }
964
#if defined(WOLFSSL_QT)
965
    /* In Qt v15.5, it calls OPENSSL_sk_free(xxx, OPENSSL_sk_free).
966
    *  By using OPENSSL_sk_free for free causes access violation.
967
    *  Therefore, switching free func to wolfSSL_ACCESS_DESCRIPTION_free
968
    *  is needed even when func isn't NULL.
969
    */
970
    if (stack->type == STACK_TYPE_ACCESS_DESCRIPTION) {
971
        func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free;
972
    }
973
#endif
974
    /* Discover free function if none provided. */
975
298
    if (func == NULL) {
976
298
        func = wolfssl_sk_get_free_func(stack->type);
977
298
    }
978
979
    /* Free all nodes and data. */
980
597
    while (stack != NULL) {
981
299
        WOLFSSL_STACK* next = stack->next;
982
983
        /* Free the data of the node. */
984
299
        if ((func != NULL) && (stack->type != STACK_TYPE_CIPHER)) {
985
299
            func(stack->data.generic);
986
299
        }
987
        /* Dispose of node. */
988
299
        XFREE(stack, stack->heap, DYNAMIC_TYPE_OPENSSL);
989
299
        stack = next;
990
299
    }
991
298
}
992
#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
993
994
/*******************************************************************************
995
 * Stack - Generic
996
 ******************************************************************************/
997
998
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
999
/* Free the nodes in the stack only.
1000
 *
1001
 * @param [in] stack  Stack of nodes.
1002
 */
1003
void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk)
1004
0
{
1005
0
    wolfSSL_sk_free(sk);
1006
0
}
1007
1008
/* Free all nodes and the dynamic data associated with them.
1009
 *
1010
 * This is an internal API.
1011
 *
1012
 * @param [in, out] sk    Stack of objects.
1013
 * @param [in]      func  Function to use to free objects.
1014
 */
1015
void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk, void (*f) (void*))
1016
0
{
1017
0
    WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free");
1018
0
    wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
1019
0
}
1020
1021
/* Put the data into a node at the top of the stack.
1022
 *
1023
 * @param [in, out] stack  Stack of objects.
1024
 * @param [in]      data   Data to store in stack.
1025
 * @return  Number of nodes in stack on success.
1026
 * @return  WOLFSSL_FAILURE when data is NULL.
1027
 * @return  WOLFSSL_FATAL_ERROR when stack is NULL.
1028
 */
1029
int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic)
1030
0
{
1031
0
    WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push");
1032
1033
0
    return wolfSSL_sk_push(sk, generic);
1034
0
}
1035
#endif
1036
1037
/*******************************************************************************
1038
 * Stack - Compression
1039
 ******************************************************************************/
1040
1041
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
1042
/* Get the number of compression algorithms in stack.
1043
 *
1044
 * @param [in] stack  Stack of compression algorithms.
1045
 * @return  Number of compression algorithms in stack on success.
1046
 * @return  0 when no compression algorithms or stack is NULL.
1047
 */
1048
int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* stack)
1049
0
{
1050
0
    return wolfSSL_sk_num(stack);
1051
0
}
1052
#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
1053
1054
#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_STUB)
1055
/* Remove all compression algorithms from stack.
1056
 *
1057
 * TBD
1058
 * Used when
1059
 *   wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
1060
 * is called.
1061
 *
1062
 * @param [in, out] stack  Stack of compression algorithms.
1063
 * @return  WOLFSSL_FAILURE always.
1064
 */
1065
int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* stack)
1066
0
{
1067
0
    (void)stack;
1068
0
    WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero");
1069
0
    return WOLFSSL_FAILURE;
1070
0
}
1071
#endif
1072
1073
/*******************************************************************************
1074
 * Stack - Cipher
1075
 ******************************************************************************/
1076
1077
#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
1078
/* Creates a new stack of ciphers.
1079
 *
1080
 * This is not an OpenSSL API.
1081
 *
1082
 * @return  Empty stack on success.
1083
 * @return  NULL when dynamic memory allocation fails.
1084
 */
1085
WOLFSSL_STACK* wolfSSL_sk_new_cipher(void)
1086
0
{
1087
0
    return wolfssl_sk_new_type(STACK_TYPE_CIPHER);
1088
0
}
1089
1090
/* Put the cipher into a node at the top of the stack.
1091
 *
1092
 * This is an internal API.
1093
 *
1094
 * @param [in, out] stack   Stack of ciphers.
1095
 * @param [in]      cipher  Cipher to store in stack.
1096
 * @return  Number of ciphers in stack on success.
1097
 * @return  WOLFSSL_FAILURE when data is NULL.
1098
 * @return  WOLFSSL_FATAL_ERROR when stack is NULL.
1099
 */
1100
int wolfSSL_sk_CIPHER_push(WOLF_STACK_OF(WOLFSSL_CIPHER)* stack,
1101
    WOLFSSL_CIPHER* cipher)
1102
0
{
1103
0
    return wolfSSL_sk_push(stack, cipher);
1104
0
}
1105
1106
#ifndef NO_WOLFSSL_STUB
1107
/* Does not do anythting at this time.
1108
 *
1109
 * @param [in, out] stack  Stack of nodes with data.
1110
 * @return  NULL always.
1111
 */
1112
WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* stack)
1113
0
{
1114
0
    WOLFSSL_STUB("wolfSSL_sk_CIPHER_pop");
1115
0
    (void)stack;
1116
0
    return NULL;
1117
0
}
1118
#endif /* NO_WOLFSSL_STUB */
1119
#endif /* WOLFSSL_QT || OPENSSL_ALL */
1120
1121
#if defined(OPENSSL_EXTRA)
1122
/* Free the nodes in the stack only.
1123
 *
1124
 * Ciphers are stored into a structure in a node and therefore don't need to be
1125
 * freed.
1126
 *
1127
 * @param [in] ciphers  Stack of ciphers.
1128
 */
1129
void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* ciphers)
1130
85.9k
{
1131
85.9k
    WOLFSSL_ENTER("wolfSSL_sk_CIPHER_free");
1132
1133
85.9k
    wolfSSL_sk_free(ciphers);
1134
85.9k
}
1135
#endif /* OPENSSL_ALL */
1136
1137
#ifdef OPENSSL_EXTRA
1138
/* Get the number of ciphers in the stack.
1139
 *
1140
 * @param [in] ciphers  Stack of ciphers.
1141
 * @return  Number of strings in stack on success.
1142
 * @return  0 when no strings or stack is NULL.
1143
 */
1144
int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* ciphers)
1145
0
{
1146
0
    WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_num");
1147
0
    return wolfSSL_sk_num(ciphers);
1148
0
}
1149
1150
/* Get the cipher from the stack at the index.
1151
 *
1152
 * @param [in] ciphers  Stack of cihers
1153
 * @param [in] i        Index of node to get cipher from.
1154
 * @return  Cipher in node at index on success.
1155
 * @return  NULL when no node at index.
1156
 */
1157
WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(WOLFSSL_STACK* ciphers, int i)
1158
0
{
1159
0
    WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_value");
1160
0
    return (WOLFSSL_CIPHER*)wolfSSL_sk_value(ciphers, i);
1161
0
}
1162
#endif
1163
1164
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
1165
/* Get the priority level of the cipher if it is in the stack.
1166
 *
1167
 * Priority level is the number of ciphers minus the idex of the cipher.
1168
 *
1169
 * @param [in] ciphers  Stack of ciphers.
1170
 * @param [in] cipher   Cipher to find in stack.
1171
 * @return  Priority level of cipher on success.
1172
 * @return  WOLFSSL_FATAL_ERROR (-1) on failure to match.
1173
 */
1174
int wolfSSL_sk_SSL_CIPHER_find(WOLF_STACK_OF(WOLFSSL_CIPHER)* ciphers,
1175
    const WOLFSSL_CIPHER* cipher)
1176
0
{
1177
0
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
1178
1179
0
    if (ciphers != NULL && cipher != NULL) {
1180
0
        int i;
1181
0
        int num = wolfSSL_sk_SSL_CIPHER_num(ciphers);
1182
0
        WOLFSSL_STACK* next = ciphers;
1183
1184
0
        for (i = 0; (i < num) && (next != NULL); i++) {
1185
            /* Match on SSL/TLS cipher suite values. */
1186
0
            if ((next->data.cipher.cipherSuite0 == cipher->cipherSuite0) &&
1187
0
                    (next->data.cipher.cipherSuite == cipher->cipherSuite)) {
1188
                /* reverse because stack pushed highest on first */
1189
0
                ret = num - i;
1190
0
                break;
1191
0
            }
1192
0
            next = next->next;
1193
0
        }
1194
0
    }
1195
1196
0
    return ret;
1197
0
}
1198
1199
/* Free the nodes in the stack only.
1200
 *
1201
 * @param [in] ciphers  Stack of ciphers.
1202
 */
1203
void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
1204
0
{
1205
0
    WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_free");
1206
0
    wolfSSL_sk_free(sk);
1207
0
}
1208
#endif /* OPENSSL_ALL || OPENSSL_EXTRA */
1209
1210
/*******************************************************************************
1211
 * Stack - String
1212
 ******************************************************************************/
1213
1214
#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
1215
    defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
1216
/* Creates a new stack of strings.
1217
 *
1218
 * @return  Empty stack on success.
1219
 * @return  NULL when dynamic memory allocation fails.
1220
 */
1221
WOLF_STACK_OF(WOLFSSL_STRING)* wolfSSL_sk_WOLFSSL_STRING_new(void)
1222
0
{
1223
0
    return wolfssl_sk_new_type(STACK_TYPE_STRING);
1224
0
}
1225
1226
/* Free the nodes and strings of the stack.
1227
 *
1228
 * OpenSSL equivalent does not free data.
1229
 *
1230
 * @param [in] strings  Stack of strings.
1231
 */
1232
void wolfSSL_sk_WOLFSSL_STRING_free(WOLF_STACK_OF(WOLFSSL_STRING)* strings)
1233
0
{
1234
0
    WOLFSSL_ENTER("wolfSSL_sk_WOLFSSL_STRING_free");
1235
1236
0
    wolfSSL_sk_pop_free(strings, NULL);
1237
0
}
1238
1239
/* Get the string from the node at an index.
1240
 *
1241
 * @param [in] strings  Stack of strings.
1242
 * @param [in] idx      Index of node.
1243
 * @return  String in node at index on success.
1244
 * @return  NULL when no node at index.
1245
 */
1246
WOLFSSL_STRING wolfSSL_sk_WOLFSSL_STRING_value(
1247
    WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx)
1248
0
{
1249
0
    return (WOLFSSL_STRING)wolfSSL_sk_value(strings, idx);
1250
0
}
1251
1252
/* Get the number of strings in the stack.
1253
 *
1254
 * @param [in] strings  Stack of strings.
1255
 * @return  Number of strings in stack on success.
1256
 * @return  0 when no strings or stack is NULL.
1257
 */
1258
int wolfSSL_sk_WOLFSSL_STRING_num(WOLF_STACK_OF(WOLFSSL_STRING)* strings)
1259
0
{
1260
0
    return wolfSSL_sk_num(strings);
1261
0
}
1262
#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
1263
1264
/*******************************************************************************
1265
 * Stack - Linear Hash
1266
 ******************************************************************************/
1267
1268
#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && defined(OPENSSL_ALL)
1269
/* Retrieve data from the stack by comparing with hash.
1270
 *
1271
 * @param [in] stack  Stack of data.
1272
 * @param [in] data   Data to look-up.
1273
 * @return  Data of node with the same hash as data passed in.
1274
 * @return  NULL when no match found.
1275
 */
1276
void *wolfSSL_lh_retrieve(WOLFSSL_STACK *stack, void *data)
1277
0
{
1278
0
    unsigned long hash;
1279
0
    void* sk_data = NULL;
1280
1281
0
    WOLFSSL_ENTER("wolfSSL_lh_retrieve");
1282
1283
    /* Validate parameters. */
1284
0
    if ((stack == NULL) || (data == NULL)) {
1285
0
        WOLFSSL_MSG("Bad parameters");
1286
0
    }
1287
0
    else if (stack->hash_fn == NULL) {
1288
0
        WOLFSSL_MSG("No hash function defined");
1289
0
    }
1290
0
    else {
1291
        /* Calculate hassh of data we are looking for. */
1292
0
        hash = stack->hash_fn(data);
1293
1294
0
        while (stack != NULL) {
1295
            /* Calculate hash if not done so yet. */
1296
0
            if (!stack->hash) {
1297
0
                sk_data = wolfssl_sk_node_get_data(stack, 0);
1298
0
                stack->hash = stack->hash_fn(sk_data);
1299
0
            }
1300
            /* Return data if hash matches. */
1301
0
            if (stack->hash == hash) {
1302
0
                if (sk_data == NULL) {
1303
0
                    sk_data = wolfssl_sk_node_get_data(stack, 0);
1304
0
                }
1305
0
                break;
1306
0
            }
1307
1308
            /* Not data to return. */
1309
0
            sk_data = NULL;
1310
0
            stack = stack->next;
1311
0
        }
1312
0
    }
1313
1314
0
    return sk_data;
1315
0
}
1316
#endif /* !NO_CERTS && OPENSSL_EXTRA && OPENSSL_ALL */
1317
1318
#endif /* !WOLFSSL_SSL_SK_INCLUDED */