Coverage Report

Created: 2025-07-18 06:15

/src/libsrtp/crypto/cipher/cipher.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * cipher.c
3
 *
4
 * cipher meta-functions
5
 *
6
 * David A. McGrew
7
 * Cisco Systems, Inc.
8
 *
9
 */
10
11
/*
12
 *
13
 * Copyright (c) 2001-2017 Cisco Systems, Inc.
14
 * All rights reserved.
15
 *
16
 * Redistribution and use in source and binary forms, with or without
17
 * modification, are permitted provided that the following conditions
18
 * are met:
19
 *
20
 *   Redistributions of source code must retain the above copyright
21
 *   notice, this list of conditions and the following disclaimer.
22
 *
23
 *   Redistributions in binary form must reproduce the above
24
 *   copyright notice, this list of conditions and the following
25
 *   disclaimer in the documentation and/or other materials provided
26
 *   with the distribution.
27
 *
28
 *   Neither the name of the Cisco Systems, Inc. nor the names of its
29
 *   contributors may be used to endorse or promote products derived
30
 *   from this software without specific prior written permission.
31
 *
32
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
36
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43
 * OF THE POSSIBILITY OF SUCH DAMAGE.
44
 *
45
 */
46
47
#ifdef HAVE_CONFIG_H
48
#include <config.h>
49
#endif
50
51
#include "cipher.h"
52
#include "cipher_priv.h"
53
#include "crypto_types.h"
54
#include "err.h"   /* for srtp_debug */
55
#include "alloc.h" /* for crypto_alloc(), crypto_free()  */
56
57
#include <stdlib.h>
58
59
srtp_debug_module_t srtp_mod_cipher = {
60
    false,   /* debugging is off by default */
61
    "cipher" /* printable module name       */
62
};
63
64
srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct,
65
                                         srtp_cipher_t **c,
66
                                         size_t key_len,
67
                                         size_t tlen)
68
12
{
69
12
    if (!ct || !ct->alloc) {
70
0
        return (srtp_err_status_bad_param);
71
0
    }
72
12
    return ((ct)->alloc((c), (key_len), (tlen)));
73
12
}
74
75
srtp_err_status_t srtp_cipher_dealloc(srtp_cipher_t *c)
76
69.1k
{
77
69.1k
    if (!c || !c->type) {
78
0
        return (srtp_err_status_bad_param);
79
0
    }
80
69.1k
    return (((c)->type)->dealloc(c));
81
69.1k
}
82
83
srtp_err_status_t srtp_cipher_init(srtp_cipher_t *c, const uint8_t *key)
84
70.0k
{
85
70.0k
    if (!c || !c->type || !c->state) {
86
0
        return (srtp_err_status_bad_param);
87
0
    }
88
70.0k
    return (((c)->type)->init(((c)->state), (key)));
89
70.0k
}
90
91
srtp_err_status_t srtp_cipher_set_iv(srtp_cipher_t *c,
92
                                     uint8_t *iv,
93
                                     srtp_cipher_direction_t direction)
94
470k
{
95
470k
    if (!c || !c->type || !c->state) {
96
0
        return (srtp_err_status_bad_param);
97
0
    }
98
99
470k
    return (((c)->type)->set_iv(((c)->state), iv, direction));
100
470k
}
101
102
srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c,
103
                                     uint8_t *buffer,
104
                                     size_t *num_octets_to_output)
105
178k
{
106
    /* zeroize the buffer */
107
178k
    octet_string_set_to_zero(buffer, *num_octets_to_output);
108
109
    /* exor keystream into buffer */
110
178k
    return (((c)->type)->encrypt(((c)->state), buffer, *num_octets_to_output,
111
178k
                                 buffer, num_octets_to_output));
112
178k
}
113
114
srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c,
115
                                      const uint8_t *src,
116
                                      size_t src_len,
117
                                      uint8_t *dst,
118
                                      size_t *dst_len)
119
224k
{
120
224k
    if (!c || !c->type || !c->state) {
121
0
        return (srtp_err_status_bad_param);
122
0
    }
123
124
224k
    return (((c)->type)->encrypt(((c)->state), src, src_len, dst, dst_len));
125
224k
}
126
127
srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c,
128
                                      const uint8_t *src,
129
                                      size_t src_len,
130
                                      uint8_t *dst,
131
                                      size_t *dst_len)
132
106k
{
133
106k
    if (!c || !c->type || !c->state) {
134
0
        return (srtp_err_status_bad_param);
135
0
    }
136
137
106k
    return (((c)->type)->decrypt(((c)->state), src, src_len, dst, dst_len));
138
106k
}
139
140
srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c,
141
                                      const uint8_t *aad,
142
                                      size_t aad_len)
143
0
{
144
0
    if (!c || !c->type || !c->state) {
145
0
        return (srtp_err_status_bad_param);
146
0
    }
147
0
    if (!((c)->type)->set_aad) {
148
0
        return (srtp_err_status_no_such_op);
149
0
    }
150
151
0
    return (((c)->type)->set_aad(((c)->state), aad, aad_len));
152
0
}
153
154
/* some bookkeeping functions */
155
156
size_t srtp_cipher_get_key_length(const srtp_cipher_t *c)
157
40.1k
{
158
40.1k
    return c->key_len;
159
40.1k
}
160
161
/*
162
 * A trivial platform independent random source.
163
 * For use in test only.
164
 */
165
void srtp_cipher_rand_for_tests(uint8_t *dest, size_t len)
166
3.07k
{
167
    /* Generic C-library (rand()) version */
168
    /* This is a random source of last resort */
169
98.7k
    while (len) {
170
95.6k
        int val = rand();
171
        /* rand() returns 0-32767 (ugh) */
172
        /* Is this a good enough way to get random bytes?
173
           It is if it passes FIPS-140... */
174
95.6k
        *dest++ = val & 0xff;
175
95.6k
        len--;
176
95.6k
    }
177
3.07k
}
178
179
/*
180
 * A trivial platform independent 32 bit random number.
181
 * For use in test only.
182
 */
183
uint32_t srtp_cipher_rand_u32_for_tests(void)
184
768
{
185
768
    uint32_t r;
186
768
    srtp_cipher_rand_for_tests((uint8_t *)&r, sizeof(r));
187
768
    return r;
188
768
}
189
190
780
#define SELF_TEST_BUF_OCTETS 128
191
774
#define NUM_RAND_TESTS 128
192
1.53k
#define MAX_KEY_LEN 64
193
/*
194
 * srtp_cipher_type_test(ct, test_data) tests a cipher of type ct against
195
 * test cases provided in a list test_data of values of key, salt, iv,
196
 * plaintext, and ciphertext that is known to be good
197
 */
198
srtp_err_status_t srtp_cipher_type_test(
199
    const srtp_cipher_type_t *ct,
200
    const srtp_cipher_test_case_t *test_data)
201
6
{
202
6
    const srtp_cipher_test_case_t *test_case = test_data;
203
6
    srtp_cipher_t *c;
204
6
    srtp_err_status_t status;
205
6
    uint8_t buffer[SELF_TEST_BUF_OCTETS];
206
6
    uint8_t buffer2[SELF_TEST_BUF_OCTETS];
207
6
    size_t len;
208
6
    size_t case_num = 0;
209
210
6
    debug_print(srtp_mod_cipher, "running self-test for cipher %s",
211
6
                ct->description);
212
213
    /*
214
     * check to make sure that we have at least one test case, and
215
     * return an error if we don't - we need to be paranoid here
216
     */
217
6
    if (test_case == NULL) {
218
0
        return srtp_err_status_cant_check;
219
0
    }
220
221
    /*
222
     * loop over all test cases, perform known-answer tests of both the
223
     * encryption and decryption functions
224
     */
225
12
    while (test_case != NULL) {
226
        /* allocate cipher */
227
6
        status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets,
228
6
                                        test_case->tag_length_octets);
229
6
        if (status) {
230
0
            return status;
231
0
        }
232
233
        /*
234
         * test the encrypt function
235
         */
236
6
        debug_print0(srtp_mod_cipher, "testing encryption");
237
238
        /* initialize cipher */
239
6
        status = srtp_cipher_init(c, test_case->key);
240
6
        if (status) {
241
0
            srtp_cipher_dealloc(c);
242
0
            return status;
243
0
        }
244
245
        /* copy plaintext into test buffer */
246
6
        if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
247
0
            srtp_cipher_dealloc(c);
248
0
            return srtp_err_status_bad_param;
249
0
        }
250
134
        for (size_t k = 0; k < test_case->plaintext_length_octets; k++) {
251
128
            buffer[k] = test_case->plaintext[k];
252
128
        }
253
254
6
        debug_print(srtp_mod_cipher, "plaintext:    %s",
255
6
                    srtp_octet_string_hex_string(
256
6
                        buffer, test_case->plaintext_length_octets));
257
258
        /* set the initialization vector */
259
6
        status = srtp_cipher_set_iv(c, test_case->idx, srtp_direction_encrypt);
260
6
        if (status) {
261
0
            srtp_cipher_dealloc(c);
262
0
            return status;
263
0
        }
264
265
6
        if (c->algorithm == SRTP_AES_GCM_128 ||
266
6
            c->algorithm == SRTP_AES_GCM_256) {
267
0
            debug_print(srtp_mod_cipher, "IV:    %s",
268
0
                        srtp_octet_string_hex_string(test_case->idx, 12));
269
270
            /*
271
             * Set the AAD
272
             */
273
0
            status = srtp_cipher_set_aad(c, test_case->aad,
274
0
                                         test_case->aad_length_octets);
275
0
            if (status) {
276
0
                srtp_cipher_dealloc(c);
277
0
                return status;
278
0
            }
279
0
            debug_print(srtp_mod_cipher, "AAD:    %s",
280
0
                        srtp_octet_string_hex_string(
281
0
                            test_case->aad, test_case->aad_length_octets));
282
0
        }
283
284
        /* encrypt */
285
6
        len = sizeof(buffer);
286
6
        status = srtp_cipher_encrypt(
287
6
            c, buffer, test_case->plaintext_length_octets, buffer, &len);
288
6
        if (status) {
289
0
            srtp_cipher_dealloc(c);
290
0
            return status;
291
0
        }
292
293
6
        debug_print(srtp_mod_cipher, "ciphertext:   %s",
294
6
                    srtp_octet_string_hex_string(
295
6
                        buffer, test_case->ciphertext_length_octets));
296
297
        /* compare the resulting ciphertext with that in the test case */
298
6
        if (len != test_case->ciphertext_length_octets) {
299
0
            srtp_cipher_dealloc(c);
300
0
            return srtp_err_status_algo_fail;
301
0
        }
302
6
        status = srtp_err_status_ok;
303
134
        for (size_t k = 0; k < test_case->ciphertext_length_octets; k++) {
304
128
            if (buffer[k] != test_case->ciphertext[k]) {
305
0
                status = srtp_err_status_algo_fail;
306
0
                debug_print(srtp_mod_cipher, "test case %zu failed", case_num);
307
0
                debug_print(srtp_mod_cipher, "(failure at byte %zu)", k);
308
0
                break;
309
0
            }
310
128
        }
311
6
        if (status) {
312
0
            debug_print(srtp_mod_cipher, "c computed: %s",
313
0
                        srtp_octet_string_hex_string(
314
0
                            buffer, 2 * test_case->plaintext_length_octets));
315
0
            debug_print(srtp_mod_cipher, "c expected: %s",
316
0
                        srtp_octet_string_hex_string(
317
0
                            test_case->ciphertext,
318
0
                            2 * test_case->plaintext_length_octets));
319
320
0
            srtp_cipher_dealloc(c);
321
0
            return srtp_err_status_algo_fail;
322
0
        }
323
324
        /*
325
         * test the decrypt function
326
         */
327
6
        debug_print0(srtp_mod_cipher, "testing decryption");
328
329
        /* re-initialize cipher for decryption */
330
6
        status = srtp_cipher_init(c, test_case->key);
331
6
        if (status) {
332
0
            srtp_cipher_dealloc(c);
333
0
            return status;
334
0
        }
335
336
        /* copy ciphertext into test buffer */
337
6
        if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
338
0
            srtp_cipher_dealloc(c);
339
0
            return srtp_err_status_bad_param;
340
0
        }
341
134
        for (size_t k = 0; k < test_case->ciphertext_length_octets; k++) {
342
128
            buffer[k] = test_case->ciphertext[k];
343
128
        }
344
345
6
        debug_print(srtp_mod_cipher, "ciphertext:    %s",
346
6
                    srtp_octet_string_hex_string(
347
6
                        buffer, test_case->plaintext_length_octets));
348
349
        /* set the initialization vector */
350
6
        status = srtp_cipher_set_iv(c, test_case->idx, srtp_direction_decrypt);
351
6
        if (status) {
352
0
            srtp_cipher_dealloc(c);
353
0
            return status;
354
0
        }
355
356
6
        if (c->algorithm == SRTP_AES_GCM_128 ||
357
6
            c->algorithm == SRTP_AES_GCM_256) {
358
            /*
359
             * Set the AAD
360
             */
361
0
            status = srtp_cipher_set_aad(c, test_case->aad,
362
0
                                         test_case->aad_length_octets);
363
0
            if (status) {
364
0
                srtp_cipher_dealloc(c);
365
0
                return status;
366
0
            }
367
0
            debug_print(srtp_mod_cipher, "AAD:    %s",
368
0
                        srtp_octet_string_hex_string(
369
0
                            test_case->aad, test_case->aad_length_octets));
370
0
        }
371
372
        /* decrypt */
373
6
        len = sizeof(buffer);
374
6
        status = srtp_cipher_decrypt(
375
6
            c, buffer, test_case->ciphertext_length_octets, buffer, &len);
376
6
        if (status) {
377
0
            srtp_cipher_dealloc(c);
378
0
            return status;
379
0
        }
380
381
6
        debug_print(srtp_mod_cipher, "plaintext:     %s",
382
6
                    srtp_octet_string_hex_string(
383
6
                        buffer, test_case->plaintext_length_octets));
384
385
        /* compare the resulting plaintext with that in the test case */
386
6
        if (len != test_case->plaintext_length_octets) {
387
0
            srtp_cipher_dealloc(c);
388
0
            return srtp_err_status_algo_fail;
389
0
        }
390
6
        status = srtp_err_status_ok;
391
134
        for (size_t k = 0; k < test_case->plaintext_length_octets; k++) {
392
128
            if (buffer[k] != test_case->plaintext[k]) {
393
0
                status = srtp_err_status_algo_fail;
394
0
                debug_print(srtp_mod_cipher, "test case %zu failed", case_num);
395
0
                debug_print(srtp_mod_cipher, "(failure at byte %zu)", k);
396
0
            }
397
128
        }
398
6
        if (status) {
399
0
            debug_print(srtp_mod_cipher, "p computed: %s",
400
0
                        srtp_octet_string_hex_string(
401
0
                            buffer, 2 * test_case->plaintext_length_octets));
402
0
            debug_print(srtp_mod_cipher, "p expected: %s",
403
0
                        srtp_octet_string_hex_string(
404
0
                            test_case->plaintext,
405
0
                            2 * test_case->plaintext_length_octets));
406
407
0
            srtp_cipher_dealloc(c);
408
0
            return srtp_err_status_algo_fail;
409
0
        }
410
411
        /* deallocate the cipher */
412
6
        status = srtp_cipher_dealloc(c);
413
6
        if (status) {
414
0
            return status;
415
0
        }
416
417
        /*
418
         * the cipher passed the test case, so move on to the next test
419
         * case in the list; if NULL, we'l proceed to the next test
420
         */
421
6
        test_case = test_case->next_test_case;
422
6
        ++case_num;
423
6
    }
424
425
    /* now run some random invertibility tests */
426
427
    /* allocate cipher, using paramaters from the first test case */
428
6
    test_case = test_data;
429
6
    status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets,
430
6
                                    test_case->tag_length_octets);
431
6
    if (status) {
432
0
        return status;
433
0
    }
434
435
774
    for (size_t j = 0; j < NUM_RAND_TESTS; j++) {
436
768
        size_t plaintext_len;
437
768
        size_t encrypted_len;
438
768
        size_t decrypted_len;
439
768
        uint8_t key[MAX_KEY_LEN];
440
768
        uint8_t iv[MAX_KEY_LEN];
441
442
        /* choose a length at random (leaving room for IV and padding) */
443
768
        plaintext_len =
444
768
            srtp_cipher_rand_u32_for_tests() % (SELF_TEST_BUF_OCTETS - 64);
445
768
        debug_print(srtp_mod_cipher, "random plaintext length %zu\n",
446
768
                    plaintext_len);
447
768
        srtp_cipher_rand_for_tests(buffer, plaintext_len);
448
449
768
        debug_print(srtp_mod_cipher, "plaintext:    %s",
450
768
                    srtp_octet_string_hex_string(buffer, plaintext_len));
451
452
        /* copy plaintext into second buffer */
453
24.7k
        for (size_t i = 0; i < plaintext_len; i++) {
454
23.9k
            buffer2[i] = buffer[i];
455
23.9k
        }
456
457
        /* choose a key at random */
458
768
        if (test_case->key_length_octets > MAX_KEY_LEN) {
459
0
            srtp_cipher_dealloc(c);
460
0
            return srtp_err_status_cant_check;
461
0
        }
462
768
        srtp_cipher_rand_for_tests(key, test_case->key_length_octets);
463
464
        /* chose a random initialization vector */
465
768
        srtp_cipher_rand_for_tests(iv, MAX_KEY_LEN);
466
467
        /* initialize cipher */
468
768
        status = srtp_cipher_init(c, key);
469
768
        if (status) {
470
0
            srtp_cipher_dealloc(c);
471
0
            return status;
472
0
        }
473
474
        /* set initialization vector */
475
768
        status = srtp_cipher_set_iv(c, test_case->idx, srtp_direction_encrypt);
476
768
        if (status) {
477
0
            srtp_cipher_dealloc(c);
478
0
            return status;
479
0
        }
480
481
768
        if (c->algorithm == SRTP_AES_GCM_128 ||
482
768
            c->algorithm == SRTP_AES_GCM_256) {
483
            /*
484
             * Set the AAD
485
             */
486
0
            status = srtp_cipher_set_aad(c, test_case->aad,
487
0
                                         test_case->aad_length_octets);
488
0
            if (status) {
489
0
                srtp_cipher_dealloc(c);
490
0
                return status;
491
0
            }
492
0
            debug_print(srtp_mod_cipher, "AAD:    %s",
493
0
                        srtp_octet_string_hex_string(
494
0
                            test_case->aad, test_case->aad_length_octets));
495
0
        }
496
497
        /* encrypt buffer with cipher */
498
768
        encrypted_len = sizeof(buffer);
499
768
        status = srtp_cipher_encrypt(c, buffer, plaintext_len, buffer,
500
768
                                     &encrypted_len);
501
768
        if (status) {
502
0
            srtp_cipher_dealloc(c);
503
0
            return status;
504
0
        }
505
506
768
        debug_print(srtp_mod_cipher, "ciphertext:   %s",
507
768
                    srtp_octet_string_hex_string(buffer, encrypted_len));
508
509
        /*
510
         * re-initialize cipher for decryption, re-set the iv, then
511
         * decrypt the ciphertext
512
         */
513
768
        status = srtp_cipher_init(c, key);
514
768
        if (status) {
515
0
            srtp_cipher_dealloc(c);
516
0
            return status;
517
0
        }
518
768
        status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx,
519
768
                                    srtp_direction_decrypt);
520
768
        if (status) {
521
0
            srtp_cipher_dealloc(c);
522
0
            return status;
523
0
        }
524
768
        if (c->algorithm == SRTP_AES_GCM_128 ||
525
768
            c->algorithm == SRTP_AES_GCM_256) {
526
            /*
527
             * Set the AAD
528
             */
529
0
            status = srtp_cipher_set_aad(c, test_case->aad,
530
0
                                         test_case->aad_length_octets);
531
0
            if (status) {
532
0
                srtp_cipher_dealloc(c);
533
0
                return status;
534
0
            }
535
0
            debug_print(srtp_mod_cipher, "AAD:    %s",
536
0
                        srtp_octet_string_hex_string(
537
0
                            test_case->aad, test_case->aad_length_octets));
538
0
        }
539
768
        decrypted_len = sizeof(buffer);
540
768
        status = srtp_cipher_decrypt(c, buffer, encrypted_len, buffer,
541
768
                                     &decrypted_len);
542
768
        if (status) {
543
0
            srtp_cipher_dealloc(c);
544
0
            return status;
545
0
        }
546
547
768
        debug_print(srtp_mod_cipher, "plaintext[2]: %s",
548
768
                    srtp_octet_string_hex_string(buffer, decrypted_len));
549
550
        /* compare the resulting plaintext with the original one */
551
768
        if (decrypted_len != plaintext_len) {
552
0
            srtp_cipher_dealloc(c);
553
0
            return srtp_err_status_algo_fail;
554
0
        }
555
768
        status = srtp_err_status_ok;
556
24.7k
        for (size_t k = 0; k < plaintext_len; k++) {
557
23.9k
            if (buffer[k] != buffer2[k]) {
558
0
                status = srtp_err_status_algo_fail;
559
0
                debug_print(srtp_mod_cipher, "random test case %zu failed",
560
0
                            case_num);
561
0
                debug_print(srtp_mod_cipher, "(failure at byte %zu)", k);
562
0
            }
563
23.9k
        }
564
768
        if (status) {
565
0
            srtp_cipher_dealloc(c);
566
0
            return srtp_err_status_algo_fail;
567
0
        }
568
768
    }
569
570
6
    status = srtp_cipher_dealloc(c);
571
6
    if (status) {
572
0
        return status;
573
0
    }
574
575
6
    return srtp_err_status_ok;
576
6
}
577
578
/*
579
 * srtp_cipher_type_self_test(ct) performs srtp_cipher_type_test on ct's
580
 * internal list of test data.
581
 */
582
srtp_err_status_t srtp_cipher_type_self_test(const srtp_cipher_type_t *ct)
583
6
{
584
6
    return srtp_cipher_type_test(ct, ct->test_data);
585
6
}
586
587
/*
588
 * cipher_bits_per_second(c, l, t) computes (an estimate of) the
589
 * number of bits that a cipher implementation can encrypt in a second
590
 *
591
 * c is a cipher (which MUST be allocated and initialized already), l
592
 * is the length in octets of the test data to be encrypted, and t is
593
 * the number of trials
594
 *
595
 * if an error is encountered, the value 0 is returned
596
 */
597
uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c,
598
                                     size_t octets_in_buffer,
599
                                     size_t num_trials)
600
0
{
601
0
    v128_t nonce;
602
0
    clock_t timer;
603
0
    uint8_t *enc_buf;
604
0
    size_t len = octets_in_buffer;
605
0
    size_t out_len;
606
0
    size_t tag_len = SRTP_MAX_TAG_LEN;
607
0
    uint8_t aad[4] = { 0, 0, 0, 0 };
608
0
    size_t aad_len = 4;
609
610
0
    enc_buf = (uint8_t *)srtp_crypto_alloc(octets_in_buffer + tag_len);
611
0
    if (enc_buf == NULL) {
612
0
        return 0; /* indicate bad parameters by returning null */
613
0
    }
614
    /* time repeated trials */
615
0
    v128_set_to_zero(&nonce);
616
0
    timer = clock();
617
0
    for (size_t i = 0; i < num_trials; i++, nonce.v32[3] = (uint32_t)i) {
618
        // Set IV
619
0
        if (srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt) !=
620
0
            srtp_err_status_ok) {
621
0
            srtp_crypto_free(enc_buf);
622
0
            return 0;
623
0
        }
624
625
        // Set (empty) AAD if supported by the cipher
626
0
        if (c->type->set_aad) {
627
0
            if (srtp_cipher_set_aad(c, aad, aad_len) != srtp_err_status_ok) {
628
0
                srtp_crypto_free(enc_buf);
629
0
                return 0;
630
0
            }
631
0
        }
632
633
        // Encrypt the buffer
634
0
        out_len = octets_in_buffer + tag_len;
635
0
        if (srtp_cipher_encrypt(c, enc_buf, len, enc_buf, &out_len) !=
636
0
            srtp_err_status_ok) {
637
0
            srtp_crypto_free(enc_buf);
638
0
            return 0;
639
0
        }
640
0
    }
641
0
    timer = clock() - timer;
642
643
0
    srtp_crypto_free(enc_buf);
644
645
0
    if (timer == 0) {
646
        /* Too fast! */
647
0
        return 0;
648
0
    }
649
650
0
    return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer;
651
0
}