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