1 /******************************************************************************
2 ** Copyright (C) 2006-2023 ascolab GmbH. All Rights Reserved.
3 ** Web: http://www.ascolab.com
5 ** SPDX-License-Identifier: GPL-2.0-or-later
7 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
8 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
10 ** Project: OpcUa Wireshark Plugin
12 ** Description: OpcUa Protocol Decoder.
14 ** Author: Gerhard Gappmeier <gerhard.gappmeier@ascolab.com>
15 ******************************************************************************/
17 #include "opcua_keyset.h"
21 #include <epan/packet.h>
23 static struct ua_keyset
*g_keysets
;
24 static unsigned int g_num_keysets
;
27 int ua_keysets_init(void)
35 int ua_keysets_clear(void)
47 * Allocates a new keyset entry.
49 * @return Returns pointer to new empty keyset.
50 * NULL would indicate an out of memory situation.
52 struct ua_keyset
*ua_keysets_add(void)
54 struct ua_keyset
*tmp
= g_realloc(g_keysets
, sizeof(*g_keysets
) * (g_num_keysets
+ 1));
55 if (tmp
== NULL
) return NULL
; /* out of mem */
56 /* realloc succeeded, assign new pointer */
58 /* return new element */
59 tmp
= &g_keysets
[g_num_keysets
++];
60 memset(tmp
, 0, sizeof(*tmp
));
61 /* default to 32 byte sig_len if missing.
62 * This is the most likely length for SHA256 based signatures,
63 * SHA1 based signatures with 16 bytes are deprecated.
65 tmp
->client_sig_len
= 32;
66 tmp
->server_sig_len
= 32;
71 * Compare function for bsearch/qsort.
72 * Sorts by keyset->id.
74 static int keyset_compare(const void *a
, const void *b
)
76 const struct ua_keyset
*keyset_a
= a
;
77 const struct ua_keyset
*keyset_b
= b
;
79 if (keyset_a
->id
== keyset_b
->id
) return 0;
80 if (keyset_a
->id
< keyset_b
->id
) return -1;
85 * Sorts the keyset to be able to use bsearch.
87 void ua_keysets_sort(void)
89 if (g_num_keysets
>= 2) {
90 qsort(g_keysets
, g_num_keysets
, sizeof(struct ua_keyset
), keyset_compare
);
97 * Looks up a keyset by id.
99 * @param id The id is 64bit value which contains the combined securechannel_id and token_id.
101 * @return Keyset if found, NULL if not found.
103 struct ua_keyset
*ua_keysets_lookup(uint64_t id
)
105 struct ua_keyset
*tmp
, key
;
107 if (!g_sorted
) return NULL
;
110 tmp
= bsearch(&key
, g_keysets
, g_num_keysets
, sizeof(struct ua_keyset
), keyset_compare
);
115 static void print_hex(unsigned char *data
, unsigned int data_len
)
119 for (i
= 0; i
< data_len
; ++i
) {
120 printf("%02X", data
[i
]);
126 * For debugging purposes only.
128 void ua_keysets_dump(void)
130 struct ua_keyset
*tmp
;
132 uint32_t channel_id
, token_id
;
134 printf("Number of keysets: %u\n", g_num_keysets
);
136 for (i
= 0; i
< g_num_keysets
; ++i
) {
138 channel_id
= (uint32_t)(tmp
->id
>> 32);
139 token_id
= (uint32_t)(tmp
->id
& 0xffffffff);
141 printf("%u: id=%" PRIu64
", channel_id=%u, token_id=%u\n", i
, tmp
->id
, channel_id
, token_id
);
143 printf("%u: client IV: ", i
);
144 print_hex(tmp
->client_iv
, sizeof(tmp
->client_iv
));
145 printf("%u: client key(%u): ", i
, tmp
->client_key_len
);
146 print_hex(tmp
->client_key
, tmp
->client_key_len
);
147 printf("%u: client sig_len(%u): ", i
, tmp
->client_sig_len
);
149 printf("%u: server IV: ", i
);
150 print_hex(tmp
->server_iv
, sizeof(tmp
->server_iv
));
151 printf("%u: server key(%u): ", i
, tmp
->server_key_len
);
152 print_hex(tmp
->server_key
, tmp
->server_key_len
);
153 printf("%u: server sig_len(%u): ", i
, tmp
->server_sig_len
);