LCOV - code coverage report
Current view: top level - crypto - s2n_locking.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 6 6 100.0 %
Date: 2025-08-15 07:28:39 Functions: 2 2 100.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License").
       5                 :            :  * You may not use this file except in compliance with the License.
       6                 :            :  * A copy of the License is located at
       7                 :            :  *
       8                 :            :  *  http://aws.amazon.com/apache2.0
       9                 :            :  *
      10                 :            :  * or in the "license" file accompanying this file. This file is distributed
      11                 :            :  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
      12                 :            :  * express or implied. See the License for the specific language governing
      13                 :            :  * permissions and limitations under the License.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "crypto/s2n_locking.h"
      17                 :            : 
      18                 :            : #include <openssl/crypto.h>
      19                 :            : #include <pthread.h>
      20                 :            : 
      21                 :            : #include "crypto/s2n_openssl.h"
      22                 :            : #include "utils/s2n_mem.h"
      23                 :            : #include "utils/s2n_safety.h"
      24                 :            : 
      25                 :            : /* Writing multithreaded applications using Openssl-1.0.2
      26                 :            :  * requires calling CRYPTO_set_locking_callback.
      27                 :            :  * If the callback is not set, locks are no-ops and unexpected
      28                 :            :  * behavior may occur, particularly for RSA and X509.
      29                 :            :  *
      30                 :            :  * In the past s2n-tls relied on customers setting the callback
      31                 :            :  * themselves, but that seems unnecessary since other parts of
      32                 :            :  * the library (like fork detection) already rely on the pthreads library.
      33                 :            :  *
      34                 :            :  * For more information:
      35                 :            :  * https://www.openssl.org/blog/blog/2017/02/21/threads/
      36                 :            :  * https://www.openssl.org/docs/man1.0.2/man3/threads.html
      37                 :            :  */
      38                 :            : 
      39                 :            : #define S2N_MUTEXES(mem) ((pthread_mutex_t *) (void *) (mem).data)
      40                 :            : 
      41                 :            : /* While the locking-related APIs "exist" in later versions of
      42                 :            :  * Openssl, they tend to be placeholders or hardcoded values like:
      43                 :            :  * #define CRYPTO_get_locking_callback() (NULL)
      44                 :            :  * So the code will compile with strange warnings / errors like
      45                 :            :  * loop conditions always being false.
      46                 :            :  */
      47                 :            : #if !(S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0))
      48                 :            : 
      49                 :            : static struct s2n_blob mutexes_mem = { 0 };
      50                 :            : static size_t mutexes_count = 0;
      51                 :            : 
      52                 :            : static void s2n_locking_cb(int mode, int n, char *file, int line)
      53                 :            : {
      54                 :            :     pthread_mutex_t *mutexes = S2N_MUTEXES(mutexes_mem);
      55                 :            :     if (!mutexes_mem.data || n < 0 || (size_t) n >= mutexes_count) {
      56                 :            :         return;
      57                 :            :     }
      58                 :            : 
      59                 :            :     if (mode & CRYPTO_LOCK) {
      60                 :            :         pthread_mutex_lock(&(mutexes[n]));
      61                 :            :     } else {
      62                 :            :         pthread_mutex_unlock(&(mutexes[n]));
      63                 :            :     }
      64                 :            : }
      65                 :            : 
      66                 :            : S2N_RESULT s2n_locking_init(void)
      67                 :            : {
      68                 :            :     if (CRYPTO_get_locking_callback() != NULL) {
      69                 :            :         return S2N_RESULT_OK;
      70                 :            :     }
      71                 :            : 
      72                 :            :     int num_locks = CRYPTO_num_locks();
      73                 :            :     RESULT_ENSURE_GTE(num_locks, 0);
      74                 :            : 
      75                 :            :     RESULT_GUARD_POSIX(s2n_realloc(&mutexes_mem, num_locks * sizeof(pthread_mutex_t)));
      76                 :            : 
      77                 :            :     pthread_mutex_t *mutexes = S2N_MUTEXES(mutexes_mem);
      78                 :            :     mutexes_count = 0;
      79                 :            :     for (size_t i = 0; i < (size_t) num_locks; i++) {
      80                 :            :         RESULT_ENSURE_EQ(pthread_mutex_init(&(mutexes[i]), NULL), 0);
      81                 :            :         mutexes_count++;
      82                 :            :     }
      83                 :            : 
      84                 :            :     CRYPTO_set_locking_callback((void (*)()) s2n_locking_cb);
      85                 :            :     return S2N_RESULT_OK;
      86                 :            : }
      87                 :            : 
      88                 :            : S2N_RESULT s2n_locking_cleanup(void)
      89                 :            : {
      90                 :            :     if (CRYPTO_get_locking_callback() == (void (*)()) s2n_locking_cb) {
      91                 :            :         CRYPTO_set_locking_callback(NULL);
      92                 :            :     }
      93                 :            : 
      94                 :            :     pthread_mutex_t *mutexes = S2N_MUTEXES(mutexes_mem);
      95                 :            :     if (mutexes) {
      96                 :            :         while (mutexes_count > 0) {
      97                 :            :             RESULT_ENSURE_EQ(pthread_mutex_destroy(&(mutexes[mutexes_count - 1])), 0);
      98                 :            :             mutexes_count--;
      99                 :            :         }
     100                 :            :         RESULT_GUARD_POSIX(s2n_free(&mutexes_mem));
     101                 :            :     }
     102                 :            : 
     103                 :            :     return S2N_RESULT_OK;
     104                 :            : }
     105                 :            : 
     106                 :            : #else
     107                 :            : 
     108                 :            : S2N_RESULT s2n_locking_init(void)
     109                 :        545 : {
     110                 :        545 :     return S2N_RESULT_OK;
     111                 :        545 : }
     112                 :            : 
     113                 :            : S2N_RESULT s2n_locking_cleanup(void)
     114                 :        545 : {
     115                 :        545 :     return S2N_RESULT_OK;
     116                 :        545 : }
     117                 :            : 
     118                 :            : #endif

Generated by: LCOV version 1.14