lax_der_parsing.c raw

   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  
 149