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