Line data Source code
1 : /* CPL_SHA256* functions derived from
2 : * http://code.google.com/p/ulib/source/browse/trunk/src/base/sha256sum.c?r=39
3 : */
4 :
5 : /* The MIT License
6 :
7 : Copyright (C) 2011 Zilong Tan (tzlloch@gmail.com)
8 : Copyright (C) 2015 Even Rouault <even.rouault at spatialys.com>
9 :
10 : Permission is hereby granted, free of charge, to any person obtaining
11 : a copy of this software and associated documentation files (the
12 : "Software"), to deal in the Software without restriction, including
13 : without limitation the rights to use, copy, modify, merge, publish,
14 : distribute, sublicense, and/or sell copies of the Software, and to
15 : permit persons to whom the Software is furnished to do so, subject to
16 : the following conditions:
17 :
18 : The above copyright notice and this permission notice shall be
19 : included in all copies or substantial portions of the Software.
20 :
21 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 : EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 : MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 : NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25 : BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26 : ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 : CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 : SOFTWARE.
29 : */
30 :
31 : /*
32 : * Original code (for SHA256 computation only) is derived from the author:
33 : * Allan Saddi
34 : */
35 :
36 : #include <string.h>
37 : #include "cpl_conv.h"
38 : #include "cpl_error.h"
39 : #include "cpl_sha256.h"
40 : #include "cpl_string.h"
41 :
42 : #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
43 : #define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
44 :
45 : #define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
46 : #define Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
47 : #define SIGMA0(x) (ROTR((x), 2) ^ ROTR((x), 13) ^ ROTR((x), 22))
48 : #define SIGMA1(x) (ROTR((x), 6) ^ ROTR((x), 11) ^ ROTR((x), 25))
49 : #define sigma0(x) (ROTR((x), 7) ^ ROTR((x), 18) ^ ((x) >> 3))
50 : #define sigma1(x) (ROTR((x), 17) ^ ROTR((x), 19) ^ ((x) >> 10))
51 :
52 : #define DO_ROUND() \
53 : { \
54 : GUInt32 t1 = h + SIGMA1(e) + Ch(e, f, g) + *(Kp++) + *(W++); \
55 : GUInt32 t2 = SIGMA0(a) + Maj(a, b, c); \
56 : h = g; \
57 : g = f; \
58 : f = e; \
59 : e = d + t1; \
60 : d = c; \
61 : c = b; \
62 : b = a; \
63 : a = t1 + t2; \
64 : }
65 :
66 : constexpr GUInt32 K[64] = {
67 : 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU,
68 : 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U, 0xd807aa98U, 0x12835b01U,
69 : 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U,
70 : 0xc19bf174U, 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
71 : 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0x983e5152U,
72 : 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U, 0xc6e00bf3U, 0xd5a79147U,
73 : 0x06ca6351U, 0x14292967U, 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU,
74 : 0x53380d13U, 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
75 : 0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U, 0xd192e819U,
76 : 0xd6990624U, 0xf40e3585U, 0x106aa070U, 0x19a4c116U, 0x1e376c08U,
77 : 0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU,
78 : 0x682e6ff3U, 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
79 : 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U};
80 :
81 : #ifdef WORDS_BIGENDIAN
82 :
83 : #define BYTESWAP(x) (x)
84 : #define BYTESWAP64(x) (x)
85 :
86 : #else // WORDS_BIGENDIAN
87 :
88 : #define BYTESWAP(x) \
89 : ((ROTR((x), 8) & 0xff00ff00U) | (ROTL((x), 8) & 0x00ff00ffU))
90 : #define BYTESWAP64(x) _byteswap64(x)
91 :
92 4797 : static inline GUInt64 _byteswap64(GUInt64 x)
93 : {
94 4797 : GUInt32 a = static_cast<GUInt32>(x >> 32);
95 4797 : GUInt32 b = static_cast<GUInt32>(x);
96 4797 : return (static_cast<GUInt64>(BYTESWAP(b)) << 32) |
97 4797 : static_cast<GUInt64>(BYTESWAP(a));
98 : }
99 :
100 : #endif /* !(WORDS_BIGENDIAN) */
101 :
102 : constexpr GByte padding[64] = {
103 : 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
109 :
110 4797 : void CPL_SHA256Init(CPL_SHA256Context *sc)
111 : {
112 4797 : sc->totalLength = 0;
113 4797 : sc->hash[0] = 0x6a09e667U;
114 4797 : sc->hash[1] = 0xbb67ae85U;
115 4797 : sc->hash[2] = 0x3c6ef372U;
116 4797 : sc->hash[3] = 0xa54ff53aU;
117 4797 : sc->hash[4] = 0x510e527fU;
118 4797 : sc->hash[5] = 0x9b05688cU;
119 4797 : sc->hash[6] = 0x1f83d9abU;
120 4797 : sc->hash[7] = 0x5be0cd19U;
121 4797 : sc->bufferLength = 0U;
122 4797 : }
123 :
124 29733 : static GUInt32 burnStack(int size)
125 : {
126 : GByte buf[128];
127 29733 : GUInt32 ret = 0;
128 :
129 29733 : memset(buf, static_cast<GByte>(size & 0xff), sizeof(buf));
130 3833340 : for (size_t i = 0; i < sizeof(buf); i++)
131 3803600 : ret += ret * buf[i];
132 29733 : size -= static_cast<int>(sizeof(buf));
133 29733 : if (size > 0)
134 19822 : ret += burnStack(size);
135 29733 : return ret;
136 : }
137 :
138 : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
139 229782 : static void CPL_SHA256Guts(CPL_SHA256Context *sc, const GUInt32 *cbuf)
140 : {
141 229782 : GUInt32 buf[64] = {};
142 :
143 229782 : GUInt32 *W = buf;
144 :
145 3906290 : for (int i = 15; i >= 0; i--)
146 : {
147 3676510 : *(W++) = BYTESWAP(*cbuf);
148 3676510 : cbuf++;
149 : }
150 :
151 229782 : GUInt32 *W16 = &buf[0];
152 229782 : GUInt32 *W15 = &buf[1];
153 229782 : GUInt32 *W7 = &buf[9];
154 229782 : GUInt32 *W2 = &buf[14];
155 :
156 11259300 : for (int i = 47; i >= 0; i--)
157 : {
158 11029500 : *(W++) = sigma1(*W2) + *(W7++) + sigma0(*W15) + *(W16++);
159 11029500 : W2++;
160 11029500 : W15++;
161 : }
162 :
163 229782 : GUInt32 a = sc->hash[0];
164 229782 : GUInt32 b = sc->hash[1];
165 229782 : GUInt32 c = sc->hash[2];
166 229782 : GUInt32 d = sc->hash[3];
167 229782 : GUInt32 e = sc->hash[4];
168 229782 : GUInt32 f = sc->hash[5];
169 229782 : GUInt32 g = sc->hash[6];
170 229782 : GUInt32 h = sc->hash[7];
171 :
172 229782 : const GUInt32 *Kp = K;
173 229782 : W = buf;
174 :
175 : #ifndef CPL_SHA256_UNROLL
176 : #define CPL_SHA256_UNROLL 1
177 : #endif /* !CPL_SHA256_UNROLL */
178 :
179 : #if CPL_SHA256_UNROLL == 1
180 14935700 : for (int i = 63; i >= 0; i--)
181 14705900 : DO_ROUND();
182 : #elif CPL_SHA256_UNROLL == 2
183 : for (int i = 31; i >= 0; i--)
184 : {
185 : DO_ROUND();
186 : DO_ROUND();
187 : }
188 : #elif CPL_SHA256_UNROLL == 4
189 : for (int i = 15; i >= 0; i--)
190 : {
191 : DO_ROUND();
192 : DO_ROUND();
193 : DO_ROUND();
194 : DO_ROUND();
195 : }
196 : #elif CPL_SHA256_UNROLL == 8
197 : for (int i = 7; i >= 0; i--)
198 : {
199 : DO_ROUND();
200 : DO_ROUND();
201 : DO_ROUND();
202 : DO_ROUND();
203 : DO_ROUND();
204 : DO_ROUND();
205 : DO_ROUND();
206 : DO_ROUND();
207 : }
208 : #elif CPL_SHA256_UNROLL == 16
209 : for (int i = 3; i >= 0; i--)
210 : {
211 : DO_ROUND();
212 : DO_ROUND();
213 : DO_ROUND();
214 : DO_ROUND();
215 : DO_ROUND();
216 : DO_ROUND();
217 : DO_ROUND();
218 : DO_ROUND();
219 : DO_ROUND();
220 : DO_ROUND();
221 : DO_ROUND();
222 : DO_ROUND();
223 : DO_ROUND();
224 : DO_ROUND();
225 : DO_ROUND();
226 : DO_ROUND();
227 : }
228 : #elif CPL_SHA256_UNROLL == 32
229 : for (int i = 1; i >= 0; i--)
230 : {
231 : DO_ROUND();
232 : DO_ROUND();
233 : DO_ROUND();
234 : DO_ROUND();
235 : DO_ROUND();
236 : DO_ROUND();
237 : DO_ROUND();
238 : DO_ROUND();
239 : DO_ROUND();
240 : DO_ROUND();
241 : DO_ROUND();
242 : DO_ROUND();
243 : DO_ROUND();
244 : DO_ROUND();
245 : DO_ROUND();
246 : DO_ROUND();
247 : DO_ROUND();
248 : DO_ROUND();
249 : DO_ROUND();
250 : DO_ROUND();
251 : DO_ROUND();
252 : DO_ROUND();
253 : DO_ROUND();
254 : DO_ROUND();
255 : DO_ROUND();
256 : DO_ROUND();
257 : DO_ROUND();
258 : DO_ROUND();
259 : DO_ROUND();
260 : DO_ROUND();
261 : DO_ROUND();
262 : DO_ROUND();
263 : }
264 : #elif CPL_SHA256_UNROLL == 64
265 : DO_ROUND();
266 : DO_ROUND();
267 : DO_ROUND();
268 : DO_ROUND();
269 : DO_ROUND();
270 : DO_ROUND();
271 : DO_ROUND();
272 : DO_ROUND();
273 : DO_ROUND();
274 : DO_ROUND();
275 : DO_ROUND();
276 : DO_ROUND();
277 : DO_ROUND();
278 : DO_ROUND();
279 : DO_ROUND();
280 : DO_ROUND();
281 : DO_ROUND();
282 : DO_ROUND();
283 : DO_ROUND();
284 : DO_ROUND();
285 : DO_ROUND();
286 : DO_ROUND();
287 : DO_ROUND();
288 : DO_ROUND();
289 : DO_ROUND();
290 : DO_ROUND();
291 : DO_ROUND();
292 : DO_ROUND();
293 : DO_ROUND();
294 : DO_ROUND();
295 : DO_ROUND();
296 : DO_ROUND();
297 : DO_ROUND();
298 : DO_ROUND();
299 : DO_ROUND();
300 : DO_ROUND();
301 : DO_ROUND();
302 : DO_ROUND();
303 : DO_ROUND();
304 : DO_ROUND();
305 : DO_ROUND();
306 : DO_ROUND();
307 : DO_ROUND();
308 : DO_ROUND();
309 : DO_ROUND();
310 : DO_ROUND();
311 : DO_ROUND();
312 : DO_ROUND();
313 : DO_ROUND();
314 : DO_ROUND();
315 : DO_ROUND();
316 : DO_ROUND();
317 : DO_ROUND();
318 : DO_ROUND();
319 : DO_ROUND();
320 : DO_ROUND();
321 : DO_ROUND();
322 : DO_ROUND();
323 : DO_ROUND();
324 : DO_ROUND();
325 : DO_ROUND();
326 : DO_ROUND();
327 : DO_ROUND();
328 : DO_ROUND();
329 : #else
330 : #error "CPL_SHA256_UNROLL must be 1, 2, 4, 8, 16, 32, or 64!"
331 : #endif
332 :
333 229782 : sc->hash[0] += a;
334 229782 : sc->hash[1] += b;
335 229782 : sc->hash[2] += c;
336 229782 : sc->hash[3] += d;
337 229782 : sc->hash[4] += e;
338 229782 : sc->hash[5] += f;
339 229782 : sc->hash[6] += g;
340 229782 : sc->hash[7] += h;
341 229782 : }
342 :
343 18471 : void CPL_SHA256Update(CPL_SHA256Context *sc, const void *data, size_t len)
344 : {
345 18471 : int needBurn = 0;
346 :
347 18471 : if (sc->bufferLength)
348 : {
349 9389 : const GUInt32 bufferBytesLeft = 64U - sc->bufferLength;
350 :
351 9389 : GUInt32 bytesToCopy = bufferBytesLeft;
352 9389 : if (bytesToCopy > len)
353 4497 : bytesToCopy = static_cast<GUInt32>(len);
354 :
355 9389 : memcpy(&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
356 :
357 9389 : sc->totalLength += bytesToCopy * 8U;
358 :
359 9389 : sc->bufferLength += bytesToCopy;
360 9389 : data = static_cast<const GByte *>(data) + bytesToCopy;
361 9389 : len -= bytesToCopy;
362 :
363 9389 : if (sc->bufferLength == 64U)
364 : {
365 4892 : CPL_SHA256Guts(sc, sc->buffer.words);
366 4892 : needBurn = 1;
367 4892 : sc->bufferLength = 0U;
368 : }
369 : }
370 :
371 243361 : while (len > 63U)
372 : {
373 224890 : sc->totalLength += 512U;
374 :
375 224890 : CPL_SHA256Guts(sc, static_cast<const GUInt32 *>(data));
376 224890 : needBurn = 1;
377 :
378 224890 : data = static_cast<const GByte *>(data) + 64U;
379 224890 : len -= 64U;
380 : }
381 :
382 18471 : if (len)
383 : {
384 4892 : memcpy(&sc->buffer.bytes[sc->bufferLength], data, len);
385 :
386 4892 : sc->totalLength += static_cast<GUInt32>(len) * 8U;
387 :
388 4892 : sc->bufferLength += static_cast<GUInt32>(len);
389 : }
390 :
391 18471 : if (needBurn)
392 : {
393 : // Clean stack state of CPL_SHA256Guts()
394 :
395 : // We add dummy side effects to avoid burnStack() to be
396 : // optimized away (#6157).
397 : static GUInt32 accumulator = 0;
398 19822 : accumulator += burnStack(
399 : static_cast<int>(sizeof(GUInt32[74]) + sizeof(GUInt32 *[6]) +
400 9911 : sizeof(int) + ((len % 2) ? sizeof(int) : 0)));
401 9911 : if (accumulator == 0xDEADBEEF)
402 0 : fprintf(stderr, "%s", ""); /*ok*/
403 : }
404 18471 : }
405 :
406 4797 : void CPL_SHA256Final(CPL_SHA256Context *sc, GByte hash[CPL_SHA256_HASH_SIZE])
407 : {
408 4797 : GUInt32 bytesToPad = 120U - sc->bufferLength;
409 4797 : if (bytesToPad > 64U)
410 4714 : bytesToPad -= 64U;
411 :
412 4797 : const GUInt64 lengthPad = BYTESWAP64(sc->totalLength);
413 :
414 4797 : CPL_SHA256Update(sc, padding, bytesToPad);
415 4797 : CPL_SHA256Update(sc, &lengthPad, 8U);
416 :
417 4797 : if (hash)
418 : {
419 43173 : for (int i = 0; i < CPL_SHA256_HASH_WORDS; i++)
420 : {
421 38376 : *reinterpret_cast<GUInt32 *>(hash) = BYTESWAP(sc->hash[i]);
422 38376 : hash += 4;
423 : }
424 : }
425 4797 : }
426 :
427 717 : void CPL_SHA256(const void *data, size_t len, GByte hash[CPL_SHA256_HASH_SIZE])
428 : {
429 : CPL_SHA256Context sSHA256Ctxt;
430 717 : CPL_SHA256Init(&sSHA256Ctxt);
431 717 : CPL_SHA256Update(&sSHA256Ctxt, data, len);
432 717 : CPL_SHA256Final(&sSHA256Ctxt, hash);
433 717 : memset(&sSHA256Ctxt, 0, sizeof(sSHA256Ctxt));
434 717 : }
435 :
436 : #define CPL_HMAC_SHA256_BLOCKSIZE 64U
437 :
438 : // See
439 : // https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Implementation
440 1967 : void CPL_HMAC_SHA256(const void *pKey, size_t nKeyLen, const void *pabyMessage,
441 : size_t nMessageLen, GByte abyDigest[CPL_SHA256_HASH_SIZE])
442 : {
443 1967 : GByte abyPad[CPL_HMAC_SHA256_BLOCKSIZE] = {};
444 1967 : if (nKeyLen > CPL_HMAC_SHA256_BLOCKSIZE)
445 : {
446 1 : CPL_SHA256(pKey, nKeyLen, abyPad);
447 : }
448 : else
449 : {
450 1966 : memcpy(abyPad, pKey, nKeyLen);
451 : }
452 :
453 : // Compute ipad.
454 127855 : for (size_t i = 0; i < CPL_HMAC_SHA256_BLOCKSIZE; i++)
455 125888 : abyPad[i] = 0x36 ^ abyPad[i];
456 :
457 : CPL_SHA256Context sSHA256Ctxt;
458 1967 : CPL_SHA256Init(&sSHA256Ctxt);
459 1967 : CPL_SHA256Update(&sSHA256Ctxt, abyPad, CPL_HMAC_SHA256_BLOCKSIZE);
460 1967 : CPL_SHA256Update(&sSHA256Ctxt, pabyMessage, nMessageLen);
461 1967 : CPL_SHA256Final(&sSHA256Ctxt, abyDigest);
462 :
463 : // Compute opad.
464 127855 : for (size_t i = 0; i < CPL_HMAC_SHA256_BLOCKSIZE; i++)
465 125888 : abyPad[i] = (0x36 ^ 0x5C) ^ abyPad[i];
466 :
467 1967 : CPL_SHA256Init(&sSHA256Ctxt);
468 1967 : CPL_SHA256Update(&sSHA256Ctxt, abyPad, CPL_HMAC_SHA256_BLOCKSIZE);
469 1967 : CPL_SHA256Update(&sSHA256Ctxt, abyDigest, CPL_SHA256_HASH_SIZE);
470 1967 : CPL_SHA256Final(&sSHA256Ctxt, abyDigest);
471 :
472 1967 : memset(&sSHA256Ctxt, 0, sizeof(sSHA256Ctxt));
473 1967 : memset(abyPad, 0, CPL_HMAC_SHA256_BLOCKSIZE);
474 1967 : }
475 :
476 : #ifdef HAVE_CRYPTOPP
477 :
478 : /* Begin of crypto++ headers */
479 : #ifdef _MSC_VER
480 : #pragma warning(push)
481 : #pragma warning(disable : 4189)
482 : #pragma warning(disable : 4512)
483 : #pragma warning(disable : 4244)
484 : #endif
485 :
486 : #ifdef __GNUC__
487 : #pragma GCC diagnostic push
488 : #pragma GCC diagnostic ignored "-Weffc++"
489 : #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
490 : #pragma GCC diagnostic ignored "-Wold-style-cast"
491 : #pragma GCC diagnostic ignored "-Wshadow"
492 : #endif
493 :
494 : #ifdef USE_ONLY_CRYPTODLL_ALG
495 : #include "cryptopp/dll.h"
496 : #else
497 : #include "cryptopp/rsa.h"
498 : #include "cryptopp/queue.h"
499 : #endif
500 :
501 : #include "cryptopp/base64.h"
502 : #include "cryptopp/osrng.h"
503 :
504 : // Fix compatibility with Crypto++
505 : #if CRYPTOPP_VERSION >= 600
506 : typedef CryptoPP::byte cryptopp_byte;
507 : #else
508 : typedef byte cryptopp_byte;
509 : #endif
510 :
511 : #ifdef __GNUC__
512 : #pragma GCC diagnostic pop
513 : #endif
514 :
515 : #ifdef _MSC_VER
516 : #pragma warning(pop)
517 : #endif
518 :
519 : #endif // HAVE_CRYPTOPP
520 :
521 : #ifdef HAVE_OPENSSL_CRYPTO
522 :
523 : #if defined(__GNUC__)
524 : #pragma GCC diagnostic push
525 : #pragma GCC diagnostic ignored "-Wold-style-cast"
526 : #endif
527 :
528 : #include <openssl/bio.h>
529 : #include <openssl/evp.h>
530 : #include <openssl/pem.h>
531 :
532 : #if defined(__GNUC__)
533 : #pragma GCC diagnostic pop
534 : #endif
535 :
536 : #endif
537 :
538 : /************************************************************************/
539 : /* CPLOpenSSLNullPassphraseCallback() */
540 : /************************************************************************/
541 :
542 : #if defined(HAVE_OPENSSL_CRYPTO)
543 0 : static int CPLOpenSSLNullPassphraseCallback(char * /*buf*/, int /*size*/,
544 : int /*rwflag*/, void * /*u*/)
545 : {
546 0 : CPLError(CE_Failure, CPLE_NotSupported,
547 : "A passphrase was required for this private key, "
548 : "but this is not supported");
549 0 : return 0;
550 : }
551 :
552 : #endif
553 :
554 : /************************************************************************/
555 : /* CPL_RSA_SHA256_Sign() */
556 : /************************************************************************/
557 :
558 7 : GByte *CPL_RSA_SHA256_Sign(const char *pszPrivateKey, const void *pabyData,
559 : unsigned int nDataLen, unsigned int *pnSignatureLen)
560 : {
561 7 : *pnSignatureLen = 0;
562 :
563 : #ifdef HAVE_CRYPTOPP
564 7 : if (EQUAL(CPLGetConfigOption("CPL_RSA_SHA256_Sign", "CRYPTOPP"),
565 : "CRYPTOPP"))
566 : {
567 : // See https://www.cryptopp.com/wiki/RSA_Cryptography
568 : // https://www.cryptopp.com/wiki/RSA_Signature_Schemes#RSA_Signature_Scheme_.28PKCS_v1.5.29
569 : // https://www.cryptopp.com/wiki/Keys_and_Formats#PEM_Encoded_Keys
570 :
571 14 : CPLString osRSAPrivKey(pszPrivateKey);
572 7 : static std::string HEADER = "-----BEGIN PRIVATE KEY-----";
573 7 : static std::string HEADER_RSA = "-----BEGIN RSA PRIVATE KEY-----";
574 : static std::string HEADER_ENCRYPTED =
575 7 : "-----BEGIN ENCRYPTED PRIVATE KEY-----";
576 7 : static std::string FOOTER = "-----END PRIVATE KEY-----";
577 :
578 : size_t pos1, pos2;
579 7 : pos1 = osRSAPrivKey.find(HEADER);
580 7 : if (pos1 == std::string::npos)
581 : {
582 0 : if (osRSAPrivKey.find(HEADER_RSA) != std::string::npos)
583 : {
584 0 : CPLError(CE_Failure, CPLE_AppDefined,
585 : "'Traditional' PEM header found, whereas PKCS#8 is "
586 : "expected. You can use for example "
587 : "'openssl pkcs8 -topk8 -inform pem -in file.key "
588 : "-outform pem -nocrypt -out file.pem' to generate "
589 : "a compatible PEM file");
590 : }
591 0 : else if (osRSAPrivKey.find(HEADER_ENCRYPTED) != std::string::npos)
592 : {
593 0 : CPLError(CE_Failure, CPLE_AppDefined,
594 : "Encrypted PEM header found. Only PKCS#8 unencrypted "
595 : "private keys are supported");
596 : }
597 : else
598 : {
599 0 : CPLError(CE_Failure, CPLE_AppDefined, "PEM header not found");
600 : }
601 0 : return nullptr;
602 : }
603 :
604 7 : pos2 = osRSAPrivKey.find(FOOTER, pos1 + 1);
605 7 : if (pos2 == std::string::npos)
606 : {
607 0 : CPLError(CE_Failure, CPLE_AppDefined, "PEM footer not found");
608 0 : return nullptr;
609 : }
610 :
611 : // Strip header and footer to get the base64-only portion
612 7 : pos1 = pos1 + HEADER.size();
613 14 : std::string osKeyB64 = osRSAPrivKey.substr(pos1, pos2 - pos1);
614 :
615 : // Base64 decode, place in a ByteQueue
616 14 : CryptoPP::ByteQueue queue;
617 14 : CryptoPP::Base64Decoder decoder;
618 :
619 7 : decoder.Attach(new CryptoPP::Redirector(queue));
620 7 : decoder.Put(reinterpret_cast<const cryptopp_byte *>(osKeyB64.data()),
621 : osKeyB64.length());
622 7 : decoder.MessageEnd();
623 :
624 14 : CryptoPP::RSA::PrivateKey rsaPrivate;
625 : try
626 : {
627 7 : rsaPrivate.BERDecode(queue);
628 : }
629 0 : catch (const std::exception &e)
630 : {
631 0 : CPLError(CE_Failure, CPLE_AppDefined,
632 0 : "Exception while decoding private key: %s", e.what());
633 0 : return nullptr;
634 : }
635 :
636 : // Check that we have consumed all bytes.
637 7 : if (!queue.IsEmpty())
638 : {
639 0 : CPLError(CE_Failure, CPLE_AppDefined,
640 : "Invalid private key: extraneous trailing bytes");
641 0 : return nullptr;
642 : }
643 :
644 14 : CryptoPP::AutoSeededRandomPool prng;
645 7 : bool valid = rsaPrivate.Validate(prng, 3);
646 7 : if (!valid)
647 : {
648 0 : CPLError(CE_Failure, CPLE_AppDefined,
649 : "Invalid private key: validation failed");
650 0 : return nullptr;
651 : }
652 :
653 14 : std::string signature;
654 : try
655 : {
656 : typedef CryptoPP::RSASS<CryptoPP::PKCS1v15,
657 : CryptoPP::SHA256>::Signer
658 : RSASSA_PKCS1v15_SHA256_Signer;
659 14 : RSASSA_PKCS1v15_SHA256_Signer signer(rsaPrivate);
660 :
661 14 : std::string message;
662 7 : message.assign(static_cast<const char *>(pabyData), nDataLen);
663 :
664 : CryptoPP::StringSource stringSource(
665 : message, true,
666 : new CryptoPP::SignerFilter(
667 7 : prng, signer, new CryptoPP::StringSink(signature)));
668 : }
669 0 : catch (const std::exception &e)
670 : {
671 0 : CPLError(CE_Failure, CPLE_AppDefined, "Exception while signing: %s",
672 0 : e.what());
673 0 : return nullptr;
674 : }
675 :
676 7 : *pnSignatureLen = static_cast<unsigned int>(signature.size());
677 : GByte *pabySignature =
678 7 : static_cast<GByte *>(CPLMalloc(signature.size()));
679 7 : memcpy(pabySignature, signature.c_str(), signature.size());
680 7 : return pabySignature;
681 : }
682 : #endif
683 :
684 : #if defined(HAVE_OPENSSL_CRYPTO)
685 0 : if (EQUAL(CPLGetConfigOption("CPL_RSA_SHA256_Sign", "OPENSSL"), "OPENSSL"))
686 : {
687 0 : const EVP_MD *digest = EVP_sha256();
688 0 : if (digest == nullptr)
689 : {
690 0 : CPLError(CE_Failure, CPLE_AppDefined, "EVP_sha256() failed");
691 0 : return nullptr;
692 : }
693 :
694 : // Old versions expect a void*, newer a const void*
695 0 : BIO *bio = BIO_new_mem_buf(
696 : const_cast<void *>(static_cast<const void *>(pszPrivateKey)),
697 0 : static_cast<int>(strlen(pszPrivateKey)));
698 0 : if (bio == nullptr)
699 : {
700 0 : CPLError(CE_Failure, CPLE_AppDefined, "BIO_new_mem_buf() failed");
701 0 : return nullptr;
702 : }
703 0 : EVP_PKEY *pkey = PEM_read_bio_PrivateKey(
704 : bio, nullptr, CPLOpenSSLNullPassphraseCallback, nullptr);
705 0 : BIO_free(bio);
706 0 : if (pkey == nullptr)
707 : {
708 0 : CPLError(CE_Failure, CPLE_AppDefined,
709 : "PEM_read_bio_PrivateKey() failed");
710 0 : return nullptr;
711 : }
712 0 : EVP_MD_CTX *md_ctx = EVP_MD_CTX_create();
713 0 : CPLAssert(md_ctx != nullptr);
714 0 : int ret = EVP_SignInit(md_ctx, digest);
715 0 : CPLAssert(ret == 1);
716 0 : ret = EVP_SignUpdate(md_ctx, pabyData, nDataLen);
717 0 : CPLAssert(ret == 1);
718 0 : const int nPKeyLength = EVP_PKEY_size(pkey);
719 0 : CPLAssert(nPKeyLength > 0);
720 0 : GByte *abyBuffer = static_cast<GByte *>(CPLMalloc(nPKeyLength));
721 0 : ret = EVP_SignFinal(md_ctx, abyBuffer, pnSignatureLen, pkey);
722 0 : if (ret != 1)
723 : {
724 0 : CPLError(CE_Failure, CPLE_AppDefined, "EVP_SignFinal() failed");
725 0 : EVP_MD_CTX_destroy(md_ctx);
726 0 : EVP_PKEY_free(pkey);
727 0 : CPLFree(abyBuffer);
728 0 : return nullptr;
729 : }
730 :
731 0 : EVP_MD_CTX_destroy(md_ctx);
732 0 : EVP_PKEY_free(pkey);
733 0 : return abyBuffer;
734 : }
735 : #endif
736 :
737 0 : CPL_IGNORE_RET_VAL(pszPrivateKey);
738 0 : CPL_IGNORE_RET_VAL(pabyData);
739 0 : CPL_IGNORE_RET_VAL(nDataLen);
740 :
741 0 : CPLError(CE_Failure, CPLE_NotSupported,
742 : "CPLRSASHA256Sign() not implemented: "
743 : "GDAL must be built against libcrypto++ or libcrypto (openssl)");
744 0 : return nullptr;
745 : }
|