]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2010-2011 Dreamhost | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
11fdf7f2 | 15 | #include "common/ceph_context.h" |
7c673cae | 16 | #include "common/config.h" |
7c673cae | 17 | #include "ceph_crypto.h" |
7c673cae | 18 | |
11fdf7f2 | 19 | #ifdef USE_NSS |
7c673cae FG |
20 | |
21 | // for SECMOD_RestartModules() | |
22 | #include <secmod.h> | |
23 | #include <nspr.h> | |
24 | ||
11fdf7f2 TL |
25 | #endif /*USE_NSS*/ |
26 | ||
27 | #ifdef USE_OPENSSL | |
28 | #include <openssl/evp.h> | |
29 | #endif /*USE_OPENSSL*/ | |
30 | ||
31 | #ifdef USE_NSS | |
32 | ||
7c673cae FG |
33 | static pthread_mutex_t crypto_init_mutex = PTHREAD_MUTEX_INITIALIZER; |
34 | static uint32_t crypto_refs = 0; | |
35 | static NSSInitContext *crypto_context = NULL; | |
36 | static pid_t crypto_init_pid = 0; | |
37 | ||
38 | void ceph::crypto::init(CephContext *cct) | |
39 | { | |
40 | pid_t pid = getpid(); | |
41 | pthread_mutex_lock(&crypto_init_mutex); | |
42 | if (crypto_init_pid != pid) { | |
43 | if (crypto_init_pid > 0) { | |
44 | SECMOD_RestartModules(PR_FALSE); | |
45 | } | |
46 | crypto_init_pid = pid; | |
47 | } | |
48 | ||
49 | if (++crypto_refs == 1) { | |
50 | NSSInitParameters init_params; | |
51 | memset(&init_params, 0, sizeof(init_params)); | |
52 | init_params.length = sizeof(init_params); | |
53 | ||
224ce89b | 54 | uint32_t flags = (NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); |
7c673cae FG |
55 | if (cct->_conf->nss_db_path.empty()) { |
56 | flags |= (NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB); | |
57 | } | |
58 | crypto_context = NSS_InitContext(cct->_conf->nss_db_path.c_str(), "", "", | |
59 | SECMOD_DB, &init_params, flags); | |
60 | } | |
61 | pthread_mutex_unlock(&crypto_init_mutex); | |
11fdf7f2 | 62 | ceph_assert_always(crypto_context != NULL); |
7c673cae FG |
63 | } |
64 | ||
65 | void ceph::crypto::shutdown(bool shared) | |
66 | { | |
67 | pthread_mutex_lock(&crypto_init_mutex); | |
11fdf7f2 | 68 | ceph_assert_always(crypto_refs > 0); |
7c673cae FG |
69 | if (--crypto_refs == 0) { |
70 | NSS_ShutdownContext(crypto_context); | |
71 | if (!shared) { | |
72 | PR_Cleanup(); | |
73 | } | |
74 | crypto_context = NULL; | |
75 | crypto_init_pid = 0; | |
76 | } | |
77 | pthread_mutex_unlock(&crypto_init_mutex); | |
78 | } | |
79 | ||
11fdf7f2 | 80 | ceph::crypto::nss::HMAC::~HMAC() |
7c673cae FG |
81 | { |
82 | PK11_DestroyContext(ctx, PR_TRUE); | |
83 | PK11_FreeSymKey(symkey); | |
84 | PK11_FreeSlot(slot); | |
85 | } | |
86 | ||
87 | #else | |
88 | # error "No supported crypto implementation found." | |
11fdf7f2 TL |
89 | #endif /*USE_NSS*/ |
90 | ||
91 | #ifdef USE_OPENSSL | |
92 | ||
93 | ceph::crypto::ssl::OpenSSLDigest::OpenSSLDigest(const EVP_MD * _type) | |
94 | : mpContext(EVP_MD_CTX_create()) | |
95 | , mpType(_type) { | |
96 | this->Restart(); | |
97 | } | |
98 | ||
99 | ceph::crypto::ssl::OpenSSLDigest::~OpenSSLDigest() { | |
100 | EVP_MD_CTX_destroy(mpContext); | |
101 | } | |
102 | ||
103 | void ceph::crypto::ssl::OpenSSLDigest::Restart() { | |
104 | EVP_DigestInit_ex(mpContext, mpType, NULL); | |
105 | } | |
106 | ||
107 | void ceph::crypto::ssl::OpenSSLDigest::Update(const unsigned char *input, size_t length) { | |
108 | if (length) { | |
109 | EVP_DigestUpdate(mpContext, const_cast<void *>(reinterpret_cast<const void *>(input)), length); | |
110 | } | |
111 | } | |
112 | ||
113 | void ceph::crypto::ssl::OpenSSLDigest::Final(unsigned char *digest) { | |
114 | unsigned int s; | |
115 | EVP_DigestFinal_ex(mpContext, digest, &s); | |
116 | } | |
117 | #endif /*USE_OPENSSL*/ | |
92f5a8d4 TL |
118 | |
119 | ||
120 | void ceph::crypto::zeroize_for_security(void* const s, const size_t n) { | |
121 | #ifdef USE_OPENSSL | |
122 | // NSS lacks its own cleaning procedure that would be resilient to | |
123 | // dead-store-elimination of nowadays compilers [1]. To avoid writing | |
124 | // our own security code, let's always use the OpenSSL's one. | |
125 | // [1]: "NSS [3.27.1] does not have a reliable memory scrubbing | |
126 | // implementation since it either calls memset or uses the macro | |
127 | // PORT_Memset, which expands to memset" | |
128 | // https://klevchen.ece.illinois.edu/pubs/yjoll-usesec17.pdf, page 11. | |
129 | OPENSSL_cleanse(s, n); | |
130 | #else | |
131 | // OpenSSL is available even when NSS is turned on. The performance- | |
132 | // critical Cephx's signature crafting machinery already follows this | |
133 | // assumption and uses OpenSSL directly (see src/auth/Crypto.cc). | |
134 | // Also, in CMakeList.txt we explicitly require both NSS and OpenSSL: | |
135 | // | |
136 | // find_package(NSS REQUIRED) | |
137 | // find_package(NSPR REQUIRED) | |
138 | // find_package(OpenSSL REQUIRED) | |
139 | # error "No supported crypto implementation found." | |
140 | #endif /*USE_OPENSSL*/ | |
141 | } |