Coverage Report

Created: 2023-06-07 06:06

/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
srtp_debug_module_t srtp_mod_cipher = {
58
    0,       /* debugging is off by default */
59
    "cipher" /* printable module name       */
60
};
61
62
srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct,
63
                                         srtp_cipher_t **c,
64
                                         int key_len,
65
                                         int tlen)
66
12
{
67
12
    if (!ct || !ct->alloc) {
68
0
        return (srtp_err_status_bad_param);
69
0
    }
70
12
    return ((ct)->alloc((c), (key_len), (tlen)));
71
12
}
72
73
srtp_err_status_t srtp_cipher_dealloc(srtp_cipher_t *c)
74
31.6k
{
75
31.6k
    if (!c || !c->type) {
76
0
        return (srtp_err_status_bad_param);
77
0
    }
78
31.6k
    return (((c)->type)->dealloc(c));
79
31.6k
}
80
81
srtp_err_status_t srtp_cipher_init(srtp_cipher_t *c, const uint8_t *key)
82
32.5k
{
83
32.5k
    if (!c || !c->type || !c->state) {
84
0
        return (srtp_err_status_bad_param);
85
0
    }
86
32.5k
    return (((c)->type)->init(((c)->state), (key)));
87
32.5k
}
88
89
srtp_err_status_t srtp_cipher_set_iv(srtp_cipher_t *c,
90
                                     uint8_t *iv,
91
                                     int direction)
92
232k
{
93
232k
    if (!c || !c->type || !c->state) {
94
0
        return (srtp_err_status_bad_param);
95
0
    }
96
97
232k
    return (((c)->type)->set_iv(((c)->state), iv, direction));
98
232k
}
99
100
srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c,
101
                                     uint8_t *buffer,
102
                                     uint32_t *num_octets_to_output)
103
46.5k
{
104
    /* zeroize the buffer */
105
46.5k
    octet_string_set_to_zero(buffer, *num_octets_to_output);
106
107
    /* exor keystream into buffer */
108
46.5k
    return (((c)->type)->encrypt(((c)->state), buffer, num_octets_to_output));
109
46.5k
}
110
111
srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c,
112
                                      uint8_t *buffer,
113
                                      uint32_t *num_octets_to_output)
114
124k
{
115
124k
    if (!c || !c->type || !c->state) {
116
0
        return (srtp_err_status_bad_param);
117
0
    }
118
119
124k
    return (((c)->type)->encrypt(((c)->state), buffer, num_octets_to_output));
120
124k
}
121
122
srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c,
123
                                      uint8_t *buffer,
124
                                      uint32_t *num_octets_to_output)
125
11.0k
{
126
11.0k
    if (!c || !c->type || !c->state) {
127
0
        return (srtp_err_status_bad_param);
128
0
    }
129
130
11.0k
    return (((c)->type)->decrypt(((c)->state), buffer, num_octets_to_output));
131
11.0k
}
132
133
srtp_err_status_t srtp_cipher_get_tag(srtp_cipher_t *c,
134
                                      uint8_t *buffer,
135
                                      uint32_t *tag_len)
136
0
{
137
0
    if (!c || !c->type || !c->state) {
138
0
        return (srtp_err_status_bad_param);
139
0
    }
140
0
    if (!((c)->type)->get_tag) {
141
0
        return (srtp_err_status_no_such_op);
142
0
    }
143
144
0
    return (((c)->type)->get_tag(((c)->state), buffer, tag_len));
145
0
}
146
147
srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c,
148
                                      const uint8_t *aad,
149
                                      uint32_t aad_len)
150
0
{
151
0
    if (!c || !c->type || !c->state) {
152
0
        return (srtp_err_status_bad_param);
153
0
    }
154
0
    if (!((c)->type)->set_aad) {
155
0
        return (srtp_err_status_no_such_op);
156
0
    }
157
158
0
    return (((c)->type)->set_aad(((c)->state), aad, aad_len));
159
0
}
160
161
/* some bookkeeping functions */
162
163
int srtp_cipher_get_key_length(const srtp_cipher_t *c)
164
18.7k
{
165
18.7k
    return c->key_len;
166
18.7k
}
167
168
/*
169
 * A trivial platform independent random source.
170
 * For use in test only.
171
 */
172
void srtp_cipher_rand_for_tests(void *dest, uint32_t len)
173
3.07k
{
174
    /* Generic C-library (rand()) version */
175
    /* This is a random source of last resort */
176
3.07k
    uint8_t *dst = (uint8_t *)dest;
177
98.7k
    while (len) {
178
95.6k
        int val = rand();
179
        /* rand() returns 0-32767 (ugh) */
180
        /* Is this a good enough way to get random bytes?
181
           It is if it passes FIPS-140... */
182
95.6k
        *dst++ = val & 0xff;
183
95.6k
        len--;
184
95.6k
    }
185
3.07k
}
186
187
/*
188
 * A trivial platform independent 32 bit random number.
189
 * For use in test only.
190
 */
191
uint32_t srtp_cipher_rand_u32_for_tests(void)
192
768
{
193
768
    uint32_t r;
194
768
    srtp_cipher_rand_for_tests(&r, sizeof(r));
195
768
    return r;
196
768
}
197
198
780
#define SELF_TEST_BUF_OCTETS 128
199
774
#define NUM_RAND_TESTS 128
200
1.53k
#define MAX_KEY_LEN 64
201
/*
202
 * srtp_cipher_type_test(ct, test_data) tests a cipher of type ct against
203
 * test cases provided in a list test_data of values of key, salt, iv,
204
 * plaintext, and ciphertext that is known to be good
205
 */
206
srtp_err_status_t srtp_cipher_type_test(
207
    const srtp_cipher_type_t *ct,
208
    const srtp_cipher_test_case_t *test_data)
209
6
{
210
6
    const srtp_cipher_test_case_t *test_case = test_data;
211
6
    srtp_cipher_t *c;
212
6
    srtp_err_status_t status;
213
6
    uint8_t buffer[SELF_TEST_BUF_OCTETS];
214
6
    uint8_t buffer2[SELF_TEST_BUF_OCTETS];
215
6
    uint32_t tag_len;
216
6
    unsigned int len;
217
6
    int i, j, case_num = 0;
218
6
    unsigned k = 0;
219
220
6
    debug_print(srtp_mod_cipher, "running self-test for cipher %s",
221
6
                ct->description);
222
223
    /*
224
     * check to make sure that we have at least one test case, and
225
     * return an error if we don't - we need to be paranoid here
226
     */
227
6
    if (test_case == NULL) {
228
0
        return srtp_err_status_cant_check;
229
0
    }
230
231
    /*
232
     * loop over all test cases, perform known-answer tests of both the
233
     * encryption and decryption functions
234
     */
235
12
    while (test_case != NULL) {
236
        /* allocate cipher */
237
6
        status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets,
238
6
                                        test_case->tag_length_octets);
239
6
        if (status) {
240
0
            return status;
241
0
        }
242
243
        /*
244
         * test the encrypt function
245
         */
246
6
        debug_print0(srtp_mod_cipher, "testing encryption");
247
248
        /* initialize cipher */
249
6
        status = srtp_cipher_init(c, test_case->key);
250
6
        if (status) {
251
0
            srtp_cipher_dealloc(c);
252
0
            return status;
253
0
        }
254
255
        /* copy plaintext into test buffer */
256
6
        if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
257
0
            srtp_cipher_dealloc(c);
258
0
            return srtp_err_status_bad_param;
259
0
        }
260
134
        for (k = 0; k < test_case->plaintext_length_octets; k++) {
261
128
            buffer[k] = test_case->plaintext[k];
262
128
        }
263
264
6
        debug_print(srtp_mod_cipher, "plaintext:    %s",
265
6
                    srtp_octet_string_hex_string(
266
6
                        buffer, test_case->plaintext_length_octets));
267
268
        /* set the initialization vector */
269
6
        status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx,
270
6
                                    srtp_direction_encrypt);
271
6
        if (status) {
272
0
            srtp_cipher_dealloc(c);
273
0
            return status;
274
0
        }
275
276
6
        if (c->algorithm == SRTP_AES_GCM_128 ||
277
6
            c->algorithm == SRTP_AES_GCM_256) {
278
0
            debug_print(srtp_mod_cipher, "IV:    %s",
279
0
                        srtp_octet_string_hex_string(test_case->idx, 12));
280
281
            /*
282
             * Set the AAD
283
             */
284
0
            status = srtp_cipher_set_aad(c, test_case->aad,
285
0
                                         test_case->aad_length_octets);
286
0
            if (status) {
287
0
                srtp_cipher_dealloc(c);
288
0
                return status;
289
0
            }
290
0
            debug_print(srtp_mod_cipher, "AAD:    %s",
291
0
                        srtp_octet_string_hex_string(
292
0
                            test_case->aad, test_case->aad_length_octets));
293
0
        }
294
295
        /* encrypt */
296
6
        len = test_case->plaintext_length_octets;
297
6
        status = srtp_cipher_encrypt(c, buffer, &len);
298
6
        if (status) {
299
0
            srtp_cipher_dealloc(c);
300
0
            return status;
301
0
        }
302
303
6
        if (c->algorithm == SRTP_AES_GCM_128 ||
304
6
            c->algorithm == SRTP_AES_GCM_256) {
305
            /*
306
             * Get the GCM tag
307
             */
308
0
            status = srtp_cipher_get_tag(c, buffer + len, &tag_len);
309
0
            if (status) {
310
0
                srtp_cipher_dealloc(c);
311
0
                return status;
312
0
            }
313
0
            len += tag_len;
314
0
        }
315
316
6
        debug_print(srtp_mod_cipher, "ciphertext:   %s",
317
6
                    srtp_octet_string_hex_string(
318
6
                        buffer, test_case->ciphertext_length_octets));
319
320
        /* compare the resulting ciphertext with that in the test case */
321
6
        if (len != test_case->ciphertext_length_octets) {
322
0
            srtp_cipher_dealloc(c);
323
0
            return srtp_err_status_algo_fail;
324
0
        }
325
6
        status = srtp_err_status_ok;
326
134
        for (k = 0; k < test_case->ciphertext_length_octets; k++) {
327
128
            if (buffer[k] != test_case->ciphertext[k]) {
328
0
                status = srtp_err_status_algo_fail;
329
0
                debug_print(srtp_mod_cipher, "test case %d failed", case_num);
330
0
                debug_print(srtp_mod_cipher, "(failure at byte %u)", k);
331
0
                break;
332
0
            }
333
128
        }
334
6
        if (status) {
335
0
            debug_print(srtp_mod_cipher, "c computed: %s",
336
0
                        srtp_octet_string_hex_string(
337
0
                            buffer, 2 * test_case->plaintext_length_octets));
338
0
            debug_print(srtp_mod_cipher, "c expected: %s",
339
0
                        srtp_octet_string_hex_string(
340
0
                            test_case->ciphertext,
341
0
                            2 * test_case->plaintext_length_octets));
342
343
0
            srtp_cipher_dealloc(c);
344
0
            return srtp_err_status_algo_fail;
345
0
        }
346
347
        /*
348
         * test the decrypt function
349
         */
350
6
        debug_print0(srtp_mod_cipher, "testing decryption");
351
352
        /* re-initialize cipher for decryption */
353
6
        status = srtp_cipher_init(c, test_case->key);
354
6
        if (status) {
355
0
            srtp_cipher_dealloc(c);
356
0
            return status;
357
0
        }
358
359
        /* copy ciphertext into test buffer */
360
6
        if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
361
0
            srtp_cipher_dealloc(c);
362
0
            return srtp_err_status_bad_param;
363
0
        }
364
134
        for (k = 0; k < test_case->ciphertext_length_octets; k++) {
365
128
            buffer[k] = test_case->ciphertext[k];
366
128
        }
367
368
6
        debug_print(srtp_mod_cipher, "ciphertext:    %s",
369
6
                    srtp_octet_string_hex_string(
370
6
                        buffer, test_case->plaintext_length_octets));
371
372
        /* set the initialization vector */
373
6
        status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx,
374
6
                                    srtp_direction_decrypt);
375
6
        if (status) {
376
0
            srtp_cipher_dealloc(c);
377
0
            return status;
378
0
        }
379
380
6
        if (c->algorithm == SRTP_AES_GCM_128 ||
381
6
            c->algorithm == SRTP_AES_GCM_256) {
382
            /*
383
             * Set the AAD
384
             */
385
0
            status = srtp_cipher_set_aad(c, test_case->aad,
386
0
                                         test_case->aad_length_octets);
387
0
            if (status) {
388
0
                srtp_cipher_dealloc(c);
389
0
                return status;
390
0
            }
391
0
            debug_print(srtp_mod_cipher, "AAD:    %s",
392
0
                        srtp_octet_string_hex_string(
393
0
                            test_case->aad, test_case->aad_length_octets));
394
0
        }
395
396
        /* decrypt */
397
6
        len = test_case->ciphertext_length_octets;
398
6
        status = srtp_cipher_decrypt(c, buffer, &len);
399
6
        if (status) {
400
0
            srtp_cipher_dealloc(c);
401
0
            return status;
402
0
        }
403
404
6
        debug_print(srtp_mod_cipher, "plaintext:   %s",
405
6
                    srtp_octet_string_hex_string(
406
6
                        buffer, test_case->plaintext_length_octets));
407
408
        /* compare the resulting plaintext with that in the test case */
409
6
        if (len != test_case->plaintext_length_octets) {
410
0
            srtp_cipher_dealloc(c);
411
0
            return srtp_err_status_algo_fail;
412
0
        }
413
6
        status = srtp_err_status_ok;
414
134
        for (k = 0; k < test_case->plaintext_length_octets; k++) {
415
128
            if (buffer[k] != test_case->plaintext[k]) {
416
0
                status = srtp_err_status_algo_fail;
417
0
                debug_print(srtp_mod_cipher, "test case %d failed", case_num);
418
0
                debug_print(srtp_mod_cipher, "(failure at byte %u)", k);
419
0
            }
420
128
        }
421
6
        if (status) {
422
0
            debug_print(srtp_mod_cipher, "p computed: %s",
423
0
                        srtp_octet_string_hex_string(
424
0
                            buffer, 2 * test_case->plaintext_length_octets));
425
0
            debug_print(srtp_mod_cipher, "p expected: %s",
426
0
                        srtp_octet_string_hex_string(
427
0
                            test_case->plaintext,
428
0
                            2 * test_case->plaintext_length_octets));
429
430
0
            srtp_cipher_dealloc(c);
431
0
            return srtp_err_status_algo_fail;
432
0
        }
433
434
        /* deallocate the cipher */
435
6
        status = srtp_cipher_dealloc(c);
436
6
        if (status) {
437
0
            return status;
438
0
        }
439
440
        /*
441
         * the cipher passed the test case, so move on to the next test
442
         * case in the list; if NULL, we'l proceed to the next test
443
         */
444
6
        test_case = test_case->next_test_case;
445
6
        ++case_num;
446
6
    }
447
448
    /* now run some random invertibility tests */
449
450
    /* allocate cipher, using paramaters from the first test case */
451
6
    test_case = test_data;
452
6
    status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets,
453
6
                                    test_case->tag_length_octets);
454
6
    if (status) {
455
0
        return status;
456
0
    }
457
458
774
    for (j = 0; j < NUM_RAND_TESTS; j++) {
459
768
        unsigned int length;
460
768
        unsigned int plaintext_len;
461
768
        uint8_t key[MAX_KEY_LEN];
462
768
        uint8_t iv[MAX_KEY_LEN];
463
464
        /* choose a length at random (leaving room for IV and padding) */
465
768
        length = srtp_cipher_rand_u32_for_tests() % (SELF_TEST_BUF_OCTETS - 64);
466
768
        debug_print(srtp_mod_cipher, "random plaintext length %d\n", length);
467
768
        srtp_cipher_rand_for_tests(buffer, length);
468
469
768
        debug_print(srtp_mod_cipher, "plaintext:    %s",
470
768
                    srtp_octet_string_hex_string(buffer, length));
471
472
        /* copy plaintext into second buffer */
473
24.7k
        for (i = 0; (unsigned int)i < length; i++) {
474
23.9k
            buffer2[i] = buffer[i];
475
23.9k
        }
476
477
        /* choose a key at random */
478
768
        if (test_case->key_length_octets > MAX_KEY_LEN) {
479
0
            srtp_cipher_dealloc(c);
480
0
            return srtp_err_status_cant_check;
481
0
        }
482
768
        srtp_cipher_rand_for_tests(key, test_case->key_length_octets);
483
484
        /* chose a random initialization vector */
485
768
        srtp_cipher_rand_for_tests(iv, MAX_KEY_LEN);
486
487
        /* initialize cipher */
488
768
        status = srtp_cipher_init(c, key);
489
768
        if (status) {
490
0
            srtp_cipher_dealloc(c);
491
0
            return status;
492
0
        }
493
494
        /* set initialization vector */
495
768
        status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx,
496
768
                                    srtp_direction_encrypt);
497
768
        if (status) {
498
0
            srtp_cipher_dealloc(c);
499
0
            return status;
500
0
        }
501
502
768
        if (c->algorithm == SRTP_AES_GCM_128 ||
503
768
            c->algorithm == SRTP_AES_GCM_256) {
504
            /*
505
             * Set the AAD
506
             */
507
0
            status = srtp_cipher_set_aad(c, test_case->aad,
508
0
                                         test_case->aad_length_octets);
509
0
            if (status) {
510
0
                srtp_cipher_dealloc(c);
511
0
                return status;
512
0
            }
513
0
            debug_print(srtp_mod_cipher, "AAD:    %s",
514
0
                        srtp_octet_string_hex_string(
515
0
                            test_case->aad, test_case->aad_length_octets));
516
0
        }
517
518
        /* encrypt buffer with cipher */
519
768
        plaintext_len = length;
520
768
        status = srtp_cipher_encrypt(c, buffer, &length);
521
768
        if (status) {
522
0
            srtp_cipher_dealloc(c);
523
0
            return status;
524
0
        }
525
768
        if (c->algorithm == SRTP_AES_GCM_128 ||
526
768
            c->algorithm == SRTP_AES_GCM_256) {
527
            /*
528
             * Get the GCM tag
529
             */
530
0
            status = srtp_cipher_get_tag(c, buffer + length, &tag_len);
531
0
            if (status) {
532
0
                srtp_cipher_dealloc(c);
533
0
                return status;
534
0
            }
535
0
            length += tag_len;
536
0
        }
537
768
        debug_print(srtp_mod_cipher, "ciphertext:   %s",
538
768
                    srtp_octet_string_hex_string(buffer, length));
539
540
        /*
541
         * re-initialize cipher for decryption, re-set the iv, then
542
         * decrypt the ciphertext
543
         */
544
768
        status = srtp_cipher_init(c, key);
545
768
        if (status) {
546
0
            srtp_cipher_dealloc(c);
547
0
            return status;
548
0
        }
549
768
        status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx,
550
768
                                    srtp_direction_decrypt);
551
768
        if (status) {
552
0
            srtp_cipher_dealloc(c);
553
0
            return status;
554
0
        }
555
768
        if (c->algorithm == SRTP_AES_GCM_128 ||
556
768
            c->algorithm == SRTP_AES_GCM_256) {
557
            /*
558
             * Set the AAD
559
             */
560
0
            status = srtp_cipher_set_aad(c, test_case->aad,
561
0
                                         test_case->aad_length_octets);
562
0
            if (status) {
563
0
                srtp_cipher_dealloc(c);
564
0
                return status;
565
0
            }
566
0
            debug_print(srtp_mod_cipher, "AAD:    %s",
567
0
                        srtp_octet_string_hex_string(
568
0
                            test_case->aad, test_case->aad_length_octets));
569
0
        }
570
768
        status = srtp_cipher_decrypt(c, buffer, &length);
571
768
        if (status) {
572
0
            srtp_cipher_dealloc(c);
573
0
            return status;
574
0
        }
575
576
768
        debug_print(srtp_mod_cipher, "plaintext[2]: %s",
577
768
                    srtp_octet_string_hex_string(buffer, length));
578
579
        /* compare the resulting plaintext with the original one */
580
768
        if (length != plaintext_len) {
581
0
            srtp_cipher_dealloc(c);
582
0
            return srtp_err_status_algo_fail;
583
0
        }
584
768
        status = srtp_err_status_ok;
585
24.7k
        for (k = 0; k < plaintext_len; k++) {
586
23.9k
            if (buffer[k] != buffer2[k]) {
587
0
                status = srtp_err_status_algo_fail;
588
0
                debug_print(srtp_mod_cipher, "random test case %d failed",
589
0
                            case_num);
590
0
                debug_print(srtp_mod_cipher, "(failure at byte %u)", k);
591
0
            }
592
23.9k
        }
593
768
        if (status) {
594
0
            srtp_cipher_dealloc(c);
595
0
            return srtp_err_status_algo_fail;
596
0
        }
597
768
    }
598
599
6
    status = srtp_cipher_dealloc(c);
600
6
    if (status) {
601
0
        return status;
602
0
    }
603
604
6
    return srtp_err_status_ok;
605
6
}
606
607
/*
608
 * srtp_cipher_type_self_test(ct) performs srtp_cipher_type_test on ct's
609
 * internal list of test data.
610
 */
611
srtp_err_status_t srtp_cipher_type_self_test(const srtp_cipher_type_t *ct)
612
6
{
613
6
    return srtp_cipher_type_test(ct, ct->test_data);
614
6
}
615
616
/*
617
 * cipher_bits_per_second(c, l, t) computes (an estimate of) the
618
 * number of bits that a cipher implementation can encrypt in a second
619
 *
620
 * c is a cipher (which MUST be allocated and initialized already), l
621
 * is the length in octets of the test data to be encrypted, and t is
622
 * the number of trials
623
 *
624
 * if an error is encountered, the value 0 is returned
625
 */
626
uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c,
627
                                     int octets_in_buffer,
628
                                     int num_trials)
629
0
{
630
0
    int i;
631
0
    v128_t nonce;
632
0
    clock_t timer;
633
0
    unsigned char *enc_buf;
634
0
    unsigned int len = octets_in_buffer;
635
0
    uint32_t tag_len = SRTP_MAX_TAG_LEN;
636
0
    unsigned char aad[4] = { 0, 0, 0, 0 };
637
0
    uint32_t aad_len = 4;
638
639
0
    enc_buf = (unsigned char *)srtp_crypto_alloc(octets_in_buffer + tag_len);
640
0
    if (enc_buf == NULL) {
641
0
        return 0; /* indicate bad parameters by returning null */
642
0
    }
643
    /* time repeated trials */
644
0
    v128_set_to_zero(&nonce);
645
0
    timer = clock();
646
0
    for (i = 0; i < num_trials; i++, nonce.v32[3] = i) {
647
        // Set IV
648
0
        if (srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt) !=
649
0
            srtp_err_status_ok) {
650
0
            srtp_crypto_free(enc_buf);
651
0
            return 0;
652
0
        }
653
654
        // Set (empty) AAD if supported by the cipher
655
0
        if (c->type->set_aad) {
656
0
            if (srtp_cipher_set_aad(c, aad, aad_len) != srtp_err_status_ok) {
657
0
                srtp_crypto_free(enc_buf);
658
0
                return 0;
659
0
            }
660
0
        }
661
662
        // Encrypt the buffer
663
0
        if (srtp_cipher_encrypt(c, enc_buf, &len) != srtp_err_status_ok) {
664
0
            srtp_crypto_free(enc_buf);
665
0
            return 0;
666
0
        }
667
668
        // Get tag if supported by the cipher
669
0
        if (c->type->get_tag) {
670
0
            if (srtp_cipher_get_tag(c, (uint8_t *)(enc_buf + len), &tag_len) !=
671
0
                srtp_err_status_ok) {
672
0
                srtp_crypto_free(enc_buf);
673
0
                return 0;
674
0
            }
675
0
        }
676
0
    }
677
0
    timer = clock() - timer;
678
679
0
    srtp_crypto_free(enc_buf);
680
681
0
    if (timer == 0) {
682
        /* Too fast! */
683
0
        return 0;
684
0
    }
685
686
0
    return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer;
687
0
}