git / moonbite-core / src/secp256k1-zkp/contrib/lax_der_parsing.c · raw

/********************************************************************** * Copyright (c) 2015 Pieter Wuille                                   * * Distributed under the MIT software license, see the accompanying   * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/#include <string.h>#include <secp256k1.h>#include "lax_der_parsing.h"int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {    size_t rpos, rlen, spos, slen;    size_t pos = 0;    size_t lenbyte;    unsigned char tmpsig[64] = {0};    int overflow = 0;    /* Hack to initialize sig with a correctly-parsed but invalid signature. */    secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);    /* Sequence tag byte */    if (pos == inputlen || input[pos] != 0x30) {        return 0;    }    pos++;    /* Sequence length bytes */    if (pos == inputlen) {        return 0;    }    lenbyte = input[pos++];    if (lenbyte & 0x80) {        lenbyte -= 0x80;        if (pos + lenbyte > inputlen) {            return 0;        }        pos += lenbyte;    }    /* Integer tag byte for R */    if (pos == inputlen || input[pos] != 0x02) {        return 0;    }    pos++;    /* Integer length for R */    if (pos == inputlen) {        return 0;    }    lenbyte = input[pos++];    if (lenbyte & 0x80) {        lenbyte -= 0x80;        if (pos + lenbyte > inputlen) {            return 0;        }        while (lenbyte > 0 && input[pos] == 0) {            pos++;            lenbyte--;        }        if (lenbyte >= sizeof(size_t)) {            return 0;        }        rlen = 0;        while (lenbyte > 0) {            rlen = (rlen << 8) + input[pos];            pos++;            lenbyte--;        }    } else {        rlen = lenbyte;    }    if (rlen > inputlen - pos) {        return 0;    }    rpos = pos;    pos += rlen;    /* Integer tag byte for S */    if (pos == inputlen || input[pos] != 0x02) {        return 0;    }    pos++;    /* Integer length for S */    if (pos == inputlen) {        return 0;    }    lenbyte = input[pos++];    if (lenbyte & 0x80) {        lenbyte -= 0x80;        if (pos + lenbyte > inputlen) {            return 0;        }        while (lenbyte > 0 && input[pos] == 0) {            pos++;            lenbyte--;        }        if (lenbyte >= sizeof(size_t)) {            return 0;        }        slen = 0;        while (lenbyte > 0) {            slen = (slen << 8) + input[pos];            pos++;            lenbyte--;        }    } else {        slen = lenbyte;    }    if (slen > inputlen - pos) {        return 0;    }    spos = pos;    pos += slen;    /* Ignore leading zeroes in R */    while (rlen > 0 && input[rpos] == 0) {        rlen--;        rpos++;    }    /* Copy R value */    if (rlen > 32) {        overflow = 1;    } else {        memcpy(tmpsig + 32 - rlen, input + rpos, rlen);    }    /* Ignore leading zeroes in S */    while (slen > 0 && input[spos] == 0) {        slen--;        spos++;    }    /* Copy S value */    if (slen > 32) {        overflow = 1;    } else {        memcpy(tmpsig + 64 - slen, input + spos, slen);    }    if (!overflow) {        overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);    }    if (overflow) {        memset(tmpsig, 0, 64);        secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);    }    return 1;}