github.com/ethereum/go-ethereum@v1.16.1/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c (about)

     1  /***********************************************************************
     2   * Copyright (c) 2015 Pieter Wuille                                    *
     3   * Distributed under the MIT software license, see the accompanying    *
     4   * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
     5   ***********************************************************************/
     6  
     7  #include <string.h>
     8  
     9  #include "lax_der_parsing.h"
    10  
    11  int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
    12      size_t rpos, rlen, spos, slen;
    13      size_t pos = 0;
    14      size_t lenbyte;
    15      unsigned char tmpsig[64] = {0};
    16      int overflow = 0;
    17  
    18      /* Hack to initialize sig with a correctly-parsed but invalid signature. */
    19      secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
    20  
    21      /* Sequence tag byte */
    22      if (pos == inputlen || input[pos] != 0x30) {
    23          return 0;
    24      }
    25      pos++;
    26  
    27      /* Sequence length bytes */
    28      if (pos == inputlen) {
    29          return 0;
    30      }
    31      lenbyte = input[pos++];
    32      if (lenbyte & 0x80) {
    33          lenbyte -= 0x80;
    34          if (lenbyte > inputlen - pos) {
    35              return 0;
    36          }
    37          pos += lenbyte;
    38      }
    39  
    40      /* Integer tag byte for R */
    41      if (pos == inputlen || input[pos] != 0x02) {
    42          return 0;
    43      }
    44      pos++;
    45  
    46      /* Integer length for R */
    47      if (pos == inputlen) {
    48          return 0;
    49      }
    50      lenbyte = input[pos++];
    51      if (lenbyte & 0x80) {
    52          lenbyte -= 0x80;
    53          if (lenbyte > inputlen - pos) {
    54              return 0;
    55          }
    56          while (lenbyte > 0 && input[pos] == 0) {
    57              pos++;
    58              lenbyte--;
    59          }
    60          if (lenbyte >= sizeof(size_t)) {
    61              return 0;
    62          }
    63          rlen = 0;
    64          while (lenbyte > 0) {
    65              rlen = (rlen << 8) + input[pos];
    66              pos++;
    67              lenbyte--;
    68          }
    69      } else {
    70          rlen = lenbyte;
    71      }
    72      if (rlen > inputlen - pos) {
    73          return 0;
    74      }
    75      rpos = pos;
    76      pos += rlen;
    77  
    78      /* Integer tag byte for S */
    79      if (pos == inputlen || input[pos] != 0x02) {
    80          return 0;
    81      }
    82      pos++;
    83  
    84      /* Integer length for S */
    85      if (pos == inputlen) {
    86          return 0;
    87      }
    88      lenbyte = input[pos++];
    89      if (lenbyte & 0x80) {
    90          lenbyte -= 0x80;
    91          if (lenbyte > inputlen - pos) {
    92              return 0;
    93          }
    94          while (lenbyte > 0 && input[pos] == 0) {
    95              pos++;
    96              lenbyte--;
    97          }
    98          if (lenbyte >= sizeof(size_t)) {
    99              return 0;
   100          }
   101          slen = 0;
   102          while (lenbyte > 0) {
   103              slen = (slen << 8) + input[pos];
   104              pos++;
   105              lenbyte--;
   106          }
   107      } else {
   108          slen = lenbyte;
   109      }
   110      if (slen > inputlen - pos) {
   111          return 0;
   112      }
   113      spos = pos;
   114  
   115      /* Ignore leading zeroes in R */
   116      while (rlen > 0 && input[rpos] == 0) {
   117          rlen--;
   118          rpos++;
   119      }
   120      /* Copy R value */
   121      if (rlen > 32) {
   122          overflow = 1;
   123      } else if (rlen) {
   124          memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
   125      }
   126  
   127      /* Ignore leading zeroes in S */
   128      while (slen > 0 && input[spos] == 0) {
   129          slen--;
   130          spos++;
   131      }
   132      /* Copy S value */
   133      if (slen > 32) {
   134          overflow = 1;
   135      } else if (slen) {
   136          memcpy(tmpsig + 64 - slen, input + spos, slen);
   137      }
   138  
   139      if (!overflow) {
   140          overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
   141      }
   142      if (overflow) {
   143          memset(tmpsig, 0, 64);
   144          secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
   145      }
   146      return 1;
   147  }
   148