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