Commit bb427bd11774f47f553257cdc0693f77b559654d
1 parent
eadc222f
SHA2: switch to pluggable crypto
Showing
8 changed files
with
225 additions
and
128 deletions
include/qpdf/QPDFCryptoImpl.hh
| @@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
| 23 | #define QPDFCRYPTOIMPL_HH | 23 | #define QPDFCRYPTOIMPL_HH |
| 24 | 24 | ||
| 25 | #include <qpdf/DLL.h> | 25 | #include <qpdf/DLL.h> |
| 26 | -#include <cstring> | 26 | +#include <string> |
| 27 | 27 | ||
| 28 | // This class is part of qpdf's pluggable crypto provider support. | 28 | // This class is part of qpdf's pluggable crypto provider support. |
| 29 | // Most users won't need to know or care about this class, but you can | 29 | // Most users won't need to know or care about this class, but you can |
| @@ -41,6 +41,8 @@ class QPDF_DLL_CLASS QPDFCryptoImpl | @@ -41,6 +41,8 @@ class QPDF_DLL_CLASS QPDFCryptoImpl | ||
| 41 | QPDF_DLL | 41 | QPDF_DLL |
| 42 | virtual ~QPDFCryptoImpl() = default; | 42 | virtual ~QPDFCryptoImpl() = default; |
| 43 | 43 | ||
| 44 | + // Hashing | ||
| 45 | + | ||
| 44 | typedef unsigned char MD5_Digest[16]; | 46 | typedef unsigned char MD5_Digest[16]; |
| 45 | QPDF_DLL | 47 | QPDF_DLL |
| 46 | virtual void MD5_init() = 0; | 48 | virtual void MD5_init() = 0; |
| @@ -51,6 +53,17 @@ class QPDF_DLL_CLASS QPDFCryptoImpl | @@ -51,6 +53,17 @@ class QPDF_DLL_CLASS QPDFCryptoImpl | ||
| 51 | QPDF_DLL | 53 | QPDF_DLL |
| 52 | virtual void MD5_digest(MD5_Digest) = 0; | 54 | virtual void MD5_digest(MD5_Digest) = 0; |
| 53 | 55 | ||
| 56 | + QPDF_DLL | ||
| 57 | + virtual void SHA2_init(int bits) = 0; | ||
| 58 | + QPDF_DLL | ||
| 59 | + virtual void SHA2_update(unsigned char const* data, size_t len) = 0; | ||
| 60 | + QPDF_DLL | ||
| 61 | + virtual void SHA2_finalize() = 0; | ||
| 62 | + QPDF_DLL | ||
| 63 | + virtual std::string SHA2_digest() = 0; | ||
| 64 | + | ||
| 65 | + // Encryption/Decryption | ||
| 66 | + | ||
| 54 | // key_len of -1 means treat key_data as a null-terminated string | 67 | // key_len of -1 means treat key_data as a null-terminated string |
| 55 | QPDF_DLL | 68 | QPDF_DLL |
| 56 | virtual void RC4_init(unsigned char const* key_data, int key_len = -1) = 0; | 69 | virtual void RC4_init(unsigned char const* key_data, int key_len = -1) = 0; |
libqpdf/Pl_SHA2.cc
0 → 100644
| 1 | +#include <qpdf/Pl_SHA2.hh> | ||
| 2 | +#include <stdexcept> | ||
| 3 | +#include <cstdio> | ||
| 4 | +#include <qpdf/PointerHolder.hh> | ||
| 5 | +#include <qpdf/QUtil.hh> | ||
| 6 | +#include <qpdf/QPDFCryptoProvider.hh> | ||
| 7 | + | ||
| 8 | +Pl_SHA2::Pl_SHA2(int bits, Pipeline* next) : | ||
| 9 | + Pipeline("sha2", next), | ||
| 10 | + in_progress(false) | ||
| 11 | +{ | ||
| 12 | + if (bits) | ||
| 13 | + { | ||
| 14 | + resetBits(bits); | ||
| 15 | + } | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +Pl_SHA2::~Pl_SHA2() | ||
| 19 | +{ | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +void | ||
| 23 | +Pl_SHA2::write(unsigned char* buf, size_t len) | ||
| 24 | +{ | ||
| 25 | + if (! this->in_progress) | ||
| 26 | + { | ||
| 27 | + this->in_progress = true; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + // Write in chunks in case len is too big to fit in an int. | ||
| 31 | + // Assume int is at least 32 bits. | ||
| 32 | + static size_t const max_bytes = 1 << 30; | ||
| 33 | + size_t bytes_left = len; | ||
| 34 | + unsigned char* data = buf; | ||
| 35 | + while (bytes_left > 0) | ||
| 36 | + { | ||
| 37 | + size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left); | ||
| 38 | + this->crypto->SHA2_update(data, bytes); | ||
| 39 | + bytes_left -= bytes; | ||
| 40 | + data += bytes; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + if (this->getNext(true)) | ||
| 44 | + { | ||
| 45 | + this->getNext()->write(buf, len); | ||
| 46 | + } | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +void | ||
| 50 | +Pl_SHA2::finish() | ||
| 51 | +{ | ||
| 52 | + if (this->getNext(true)) | ||
| 53 | + { | ||
| 54 | + this->getNext()->finish(); | ||
| 55 | + } | ||
| 56 | + this->crypto->SHA2_finalize(); | ||
| 57 | + this->in_progress = false; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +void | ||
| 61 | +Pl_SHA2::resetBits(int bits) | ||
| 62 | +{ | ||
| 63 | + if (this->in_progress) | ||
| 64 | + { | ||
| 65 | + throw std::logic_error( | ||
| 66 | + "bit reset requested for in-progress SHA2 Pipeline"); | ||
| 67 | + } | ||
| 68 | + this->crypto = QPDFCryptoProvider::getImpl(); | ||
| 69 | + this->crypto->SHA2_init(bits); | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +std::string | ||
| 73 | +Pl_SHA2::getRawDigest() | ||
| 74 | +{ | ||
| 75 | + if (this->in_progress) | ||
| 76 | + { | ||
| 77 | + throw std::logic_error( | ||
| 78 | + "digest requested for in-progress SHA2 Pipeline"); | ||
| 79 | + } | ||
| 80 | + return this->crypto->SHA2_digest(); | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +std::string | ||
| 84 | +Pl_SHA2::getHexDigest() | ||
| 85 | +{ | ||
| 86 | + if (this->in_progress) | ||
| 87 | + { | ||
| 88 | + throw std::logic_error( | ||
| 89 | + "digest requested for in-progress SHA2 Pipeline"); | ||
| 90 | + } | ||
| 91 | + return QUtil::hex_encode(getRawDigest()); | ||
| 92 | +} |
libqpdf/QPDFCrypto_native.cc
| @@ -42,3 +42,27 @@ void | @@ -42,3 +42,27 @@ void | ||
| 42 | QPDFCrypto_native::RC4_finalize() | 42 | QPDFCrypto_native::RC4_finalize() |
| 43 | { | 43 | { |
| 44 | } | 44 | } |
| 45 | + | ||
| 46 | +void | ||
| 47 | +QPDFCrypto_native::SHA2_init(int bits) | ||
| 48 | +{ | ||
| 49 | + this->sha2 = std::make_shared<SHA2_native>(bits); | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +void | ||
| 53 | +QPDFCrypto_native::SHA2_update(unsigned char const* data, size_t len) | ||
| 54 | +{ | ||
| 55 | + this->sha2->update(data, len); | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +void | ||
| 59 | +QPDFCrypto_native::SHA2_finalize() | ||
| 60 | +{ | ||
| 61 | + this->sha2->finalize(); | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +std::string | ||
| 65 | +QPDFCrypto_native::SHA2_digest() | ||
| 66 | +{ | ||
| 67 | + return this->sha2->getRawDigest(); | ||
| 68 | +} |
libqpdf/SHA2_native.cc
| 1 | -#include <qpdf/Pl_SHA2.hh> | 1 | +#include <qpdf/SHA2_native.hh> |
| 2 | #include <stdexcept> | 2 | #include <stdexcept> |
| 3 | #include <cstdio> | 3 | #include <cstdio> |
| 4 | #include <qpdf/PointerHolder.hh> | 4 | #include <qpdf/PointerHolder.hh> |
| 5 | #include <qpdf/QUtil.hh> | 5 | #include <qpdf/QUtil.hh> |
| 6 | 6 | ||
| 7 | -Pl_SHA2::Pl_SHA2(int bits, Pipeline* next) : | ||
| 8 | - Pipeline("sha2", next), | ||
| 9 | - in_progress(false), | ||
| 10 | - bits(0) | 7 | + |
| 8 | +SHA2_native::SHA2_native(int bits) : | ||
| 9 | + bits(bits) | ||
| 11 | { | 10 | { |
| 12 | - if (bits) | 11 | + switch (bits) |
| 13 | { | 12 | { |
| 14 | - resetBits(bits); | 13 | + case 256: |
| 14 | + sph_sha256_init(&this->ctx256); | ||
| 15 | + break; | ||
| 16 | + case 384: | ||
| 17 | + sph_sha384_init(&this->ctx384); | ||
| 18 | + break; | ||
| 19 | + case 512: | ||
| 20 | + sph_sha512_init(&this->ctx512); | ||
| 21 | + break; | ||
| 22 | + default: | ||
| 23 | + badBits(); | ||
| 24 | + break; | ||
| 15 | } | 25 | } |
| 16 | } | 26 | } |
| 17 | 27 | ||
| 18 | -Pl_SHA2::~Pl_SHA2() | ||
| 19 | -{ | ||
| 20 | -} | ||
| 21 | - | ||
| 22 | void | 28 | void |
| 23 | -Pl_SHA2::badBits() | 29 | +SHA2_native::badBits() |
| 24 | { | 30 | { |
| 25 | - throw std::logic_error("Pl_SHA2 has unexpected value for bits"); | 31 | + throw std::logic_error("SHA2_native has bits != 256, 384, or 512"); |
| 26 | } | 32 | } |
| 27 | 33 | ||
| 28 | void | 34 | void |
| 29 | -Pl_SHA2::write(unsigned char* buf, size_t len) | 35 | +SHA2_native::update(unsigned char const* buf, size_t len) |
| 30 | { | 36 | { |
| 31 | - if (! this->in_progress) | ||
| 32 | - { | ||
| 33 | - switch (bits) | ||
| 34 | - { | ||
| 35 | - case 256: | ||
| 36 | - sph_sha256_init(&this->ctx256); | ||
| 37 | - break; | ||
| 38 | - case 384: | ||
| 39 | - sph_sha384_init(&this->ctx384); | ||
| 40 | - break; | ||
| 41 | - case 512: | ||
| 42 | - sph_sha512_init(&this->ctx512); | ||
| 43 | - break; | ||
| 44 | - default: | ||
| 45 | - badBits(); | ||
| 46 | - break; | ||
| 47 | - } | ||
| 48 | - this->in_progress = true; | ||
| 49 | - } | ||
| 50 | - | ||
| 51 | - // Write in chunks in case len is too big to fit in an int. | ||
| 52 | - // Assume int is at least 32 bits. | ||
| 53 | - static size_t const max_bytes = 1 << 30; | ||
| 54 | - size_t bytes_left = len; | ||
| 55 | - unsigned char* data = buf; | ||
| 56 | - while (bytes_left > 0) | ||
| 57 | - { | ||
| 58 | - size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left); | ||
| 59 | - switch (bits) | ||
| 60 | - { | ||
| 61 | - case 256: | ||
| 62 | - sph_sha256(&this->ctx256, data, bytes); | ||
| 63 | - break; | ||
| 64 | - case 384: | ||
| 65 | - sph_sha384(&this->ctx384, data, bytes); | ||
| 66 | - break; | ||
| 67 | - case 512: | ||
| 68 | - sph_sha512(&this->ctx512, data, bytes); | ||
| 69 | - break; | ||
| 70 | - default: | ||
| 71 | - badBits(); | ||
| 72 | - break; | ||
| 73 | - } | ||
| 74 | - bytes_left -= bytes; | ||
| 75 | - data += bytes; | ||
| 76 | - } | ||
| 77 | - | ||
| 78 | - if (this->getNext(true)) | 37 | + switch (bits) |
| 79 | { | 38 | { |
| 80 | - this->getNext()->write(buf, len); | 39 | + case 256: |
| 40 | + sph_sha256(&this->ctx256, buf, len); | ||
| 41 | + break; | ||
| 42 | + case 384: | ||
| 43 | + sph_sha384(&this->ctx384, buf, len); | ||
| 44 | + break; | ||
| 45 | + case 512: | ||
| 46 | + sph_sha512(&this->ctx512, buf, len); | ||
| 47 | + break; | ||
| 48 | + default: | ||
| 49 | + badBits(); | ||
| 50 | + break; | ||
| 81 | } | 51 | } |
| 82 | } | 52 | } |
| 83 | 53 | ||
| 84 | void | 54 | void |
| 85 | -Pl_SHA2::finish() | 55 | +SHA2_native::finalize() |
| 86 | { | 56 | { |
| 87 | - if (this->getNext(true)) | ||
| 88 | - { | ||
| 89 | - this->getNext()->finish(); | ||
| 90 | - } | ||
| 91 | switch (bits) | 57 | switch (bits) |
| 92 | { | 58 | { |
| 93 | case 256: | 59 | case 256: |
| @@ -103,26 +69,10 @@ Pl_SHA2::finish() | @@ -103,26 +69,10 @@ Pl_SHA2::finish() | ||
| 103 | badBits(); | 69 | badBits(); |
| 104 | break; | 70 | break; |
| 105 | } | 71 | } |
| 106 | - this->in_progress = false; | ||
| 107 | -} | ||
| 108 | - | ||
| 109 | -void | ||
| 110 | -Pl_SHA2::resetBits(int bits) | ||
| 111 | -{ | ||
| 112 | - if (this->in_progress) | ||
| 113 | - { | ||
| 114 | - throw std::logic_error( | ||
| 115 | - "bit reset requested for in-progress SHA2 Pipeline"); | ||
| 116 | - } | ||
| 117 | - if (! ((bits == 256) || (bits == 384) || (bits == 512))) | ||
| 118 | - { | ||
| 119 | - throw std::logic_error("Pl_SHA2 called with bits != 256, 384, or 512"); | ||
| 120 | - } | ||
| 121 | - this->bits = bits; | ||
| 122 | } | 72 | } |
| 123 | 73 | ||
| 124 | std::string | 74 | std::string |
| 125 | -Pl_SHA2::getRawDigest() | 75 | +SHA2_native::getRawDigest() |
| 126 | { | 76 | { |
| 127 | std::string result; | 77 | std::string result; |
| 128 | switch (bits) | 78 | switch (bits) |
| @@ -145,14 +95,3 @@ Pl_SHA2::getRawDigest() | @@ -145,14 +95,3 @@ Pl_SHA2::getRawDigest() | ||
| 145 | } | 95 | } |
| 146 | return result; | 96 | return result; |
| 147 | } | 97 | } |
| 148 | - | ||
| 149 | -std::string | ||
| 150 | -Pl_SHA2::getHexDigest() | ||
| 151 | -{ | ||
| 152 | - if (this->in_progress) | ||
| 153 | - { | ||
| 154 | - throw std::logic_error( | ||
| 155 | - "digest requested for in-progress SHA2 Pipeline"); | ||
| 156 | - } | ||
| 157 | - return QUtil::hex_encode(getRawDigest()); | ||
| 158 | -} |
libqpdf/build.mk
| @@ -79,6 +79,7 @@ SRCS_libqpdf = \ | @@ -79,6 +79,7 @@ SRCS_libqpdf = \ | ||
| 79 | libqpdf/QUtil.cc \ | 79 | libqpdf/QUtil.cc \ |
| 80 | libqpdf/RC4.cc \ | 80 | libqpdf/RC4.cc \ |
| 81 | libqpdf/RC4_native.cc \ | 81 | libqpdf/RC4_native.cc \ |
| 82 | + libqpdf/SHA2_native.cc \ | ||
| 82 | libqpdf/SecureRandomDataProvider.cc \ | 83 | libqpdf/SecureRandomDataProvider.cc \ |
| 83 | libqpdf/SparseOHArray.cc \ | 84 | libqpdf/SparseOHArray.cc \ |
| 84 | libqpdf/qpdf-c.cc \ | 85 | libqpdf/qpdf-c.cc \ |
libqpdf/qpdf/Pl_SHA2.hh
0 → 100644
| 1 | +#ifndef PL_SHA2_HH | ||
| 2 | +#define PL_SHA2_HH | ||
| 3 | + | ||
| 4 | +// Bits must be a supported number of bits, currently only 256, 384, | ||
| 5 | +// or 512. Passing 0 as bits leaves the pipeline uncommitted, in | ||
| 6 | +// which case resetBits must be called before the pipeline is used. | ||
| 7 | +// If a next is provided, this pipeline sends its output to its | ||
| 8 | +// successor unmodified. After calling finish, the SHA2 checksum of | ||
| 9 | +// the data that passed through the pipeline is available. | ||
| 10 | + | ||
| 11 | +// This pipeline is reusable; i.e., it is safe to call write() after | ||
| 12 | +// calling finish(). The first call to write() after a call to | ||
| 13 | +// finish() initializes a new SHA2 object. resetBits may also be | ||
| 14 | +// called between finish and the next call to write. | ||
| 15 | + | ||
| 16 | +#include <qpdf/Pipeline.hh> | ||
| 17 | +#include <qpdf/QPDFCryptoImpl.hh> | ||
| 18 | +#include <memory> | ||
| 19 | + | ||
| 20 | +class Pl_SHA2: public Pipeline | ||
| 21 | +{ | ||
| 22 | + public: | ||
| 23 | + QPDF_DLL | ||
| 24 | + Pl_SHA2(int bits = 0, Pipeline* next = 0); | ||
| 25 | + QPDF_DLL | ||
| 26 | + virtual ~Pl_SHA2(); | ||
| 27 | + QPDF_DLL | ||
| 28 | + virtual void write(unsigned char*, size_t); | ||
| 29 | + QPDF_DLL | ||
| 30 | + virtual void finish(); | ||
| 31 | + QPDF_DLL | ||
| 32 | + void resetBits(int bits); | ||
| 33 | + QPDF_DLL | ||
| 34 | + std::string getHexDigest(); | ||
| 35 | + QPDF_DLL | ||
| 36 | + std::string getRawDigest(); | ||
| 37 | + | ||
| 38 | + private: | ||
| 39 | + bool in_progress; | ||
| 40 | + std::shared_ptr<QPDFCryptoImpl> crypto; | ||
| 41 | +}; | ||
| 42 | + | ||
| 43 | +#endif // PL_SHA2_HH |
libqpdf/qpdf/QPDFCrypto_native.hh
| @@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
| 5 | #include <qpdf/QPDFCryptoImpl.hh> | 5 | #include <qpdf/QPDFCryptoImpl.hh> |
| 6 | #include <qpdf/MD5_native.hh> | 6 | #include <qpdf/MD5_native.hh> |
| 7 | #include <qpdf/RC4_native.hh> | 7 | #include <qpdf/RC4_native.hh> |
| 8 | +#include <qpdf/SHA2_native.hh> | ||
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | 10 | ||
| 10 | class QPDFCrypto_native: public QPDFCryptoImpl | 11 | class QPDFCrypto_native: public QPDFCryptoImpl |
| @@ -25,9 +26,15 @@ class QPDFCrypto_native: public QPDFCryptoImpl | @@ -25,9 +26,15 @@ class QPDFCrypto_native: public QPDFCryptoImpl | ||
| 25 | unsigned char* out_data = 0); | 26 | unsigned char* out_data = 0); |
| 26 | virtual void RC4_finalize(); | 27 | virtual void RC4_finalize(); |
| 27 | 28 | ||
| 29 | + virtual void SHA2_init(int bits); | ||
| 30 | + virtual void SHA2_update(unsigned char const* data, size_t len); | ||
| 31 | + virtual void SHA2_finalize(); | ||
| 32 | + virtual std::string SHA2_digest(); | ||
| 33 | + | ||
| 28 | private: | 34 | private: |
| 29 | std::shared_ptr<MD5_native> md5; | 35 | std::shared_ptr<MD5_native> md5; |
| 30 | std::shared_ptr<RC4_native> rc4; | 36 | std::shared_ptr<RC4_native> rc4; |
| 37 | + std::shared_ptr<SHA2_native> sha2; | ||
| 31 | }; | 38 | }; |
| 32 | 39 | ||
| 33 | #endif // QPDFCRYPTO_NATIVE_HH | 40 | #endif // QPDFCRYPTO_NATIVE_HH |
libqpdf/qpdf/SHA2_native.hh
| 1 | -#ifndef PL_SHA2_HH | ||
| 2 | -#define PL_SHA2_HH | 1 | +#ifndef SHA2_NATIVE_HH |
| 2 | +#define SHA2_NATIVE_HH | ||
| 3 | 3 | ||
| 4 | -// Bits must be a supported number of bits, currently only 256, 384, | ||
| 5 | -// or 512. Passing 0 as bits leaves the pipeline uncommitted, in | ||
| 6 | -// which case resetBits must be called before the pipeline is used. | ||
| 7 | -// If a next is provided, this pipeline sends its output to its | ||
| 8 | -// successor unmodified. After calling finish, the SHA2 checksum of | ||
| 9 | -// the data that passed through the pipeline is available. | ||
| 10 | - | ||
| 11 | -// This pipeline is reusable; i.e., it is safe to call write() after | ||
| 12 | -// calling finish(). The first call to write() after a call to | ||
| 13 | -// finish() initializes a new SHA2 object. resetBits may also be | ||
| 14 | -// called between finish and the next call to write. | ||
| 15 | - | ||
| 16 | -#include <qpdf/Pipeline.hh> | ||
| 17 | #include <sph/sph_sha2.h> | 4 | #include <sph/sph_sha2.h> |
| 5 | +#include <string> | ||
| 18 | 6 | ||
| 19 | -class Pl_SHA2: public Pipeline | 7 | +class SHA2_native |
| 20 | { | 8 | { |
| 21 | public: | 9 | public: |
| 22 | - QPDF_DLL | ||
| 23 | - Pl_SHA2(int bits = 0, Pipeline* next = 0); | ||
| 24 | - QPDF_DLL | ||
| 25 | - virtual ~Pl_SHA2(); | ||
| 26 | - QPDF_DLL | ||
| 27 | - virtual void write(unsigned char*, size_t); | ||
| 28 | - QPDF_DLL | ||
| 29 | - virtual void finish(); | ||
| 30 | - QPDF_DLL | ||
| 31 | - void resetBits(int bits); | ||
| 32 | - QPDF_DLL | ||
| 33 | - std::string getHexDigest(); | ||
| 34 | - QPDF_DLL | 10 | + SHA2_native(int bits); |
| 11 | + ~SHA2_native() = default; | ||
| 12 | + void update(unsigned char const* const, size_t); | ||
| 13 | + void finalize(); | ||
| 35 | std::string getRawDigest(); | 14 | std::string getRawDigest(); |
| 36 | 15 | ||
| 37 | private: | 16 | private: |
| 38 | void badBits(); | 17 | void badBits(); |
| 39 | 18 | ||
| 40 | - bool in_progress; | ||
| 41 | int bits; | 19 | int bits; |
| 42 | sph_sha256_context ctx256; | 20 | sph_sha256_context ctx256; |
| 43 | sph_sha384_context ctx384; | 21 | sph_sha384_context ctx384; |
| @@ -47,4 +25,4 @@ class Pl_SHA2: public Pipeline | @@ -47,4 +25,4 @@ class Pl_SHA2: public Pipeline | ||
| 47 | unsigned char sha512sum[64]; | 25 | unsigned char sha512sum[64]; |
| 48 | }; | 26 | }; |
| 49 | 27 | ||
| 50 | -#endif // PL_SHA2_HH | 28 | +#endif // SHA2_NATIVE_HH |