LCOV - code coverage report
Current view: top level - powhsm/src - btctx.c (source / functions) Hit Total Coverage
Test: powHSM firmware Lines: 135 140 96.4 %
Date: 2025-07-10 13:49:13 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /**
       2             :  * The MIT License (MIT)
       3             :  *
       4             :  * Copyright (c) 2021 RSK Labs Ltd
       5             :  *
       6             :  * Permission is hereby granted, free of charge, to any person obtaining a copy
       7             :  * of this software and associated documentation files (the "Software"), to
       8             :  * deal in the Software without restriction, including without limitation the
       9             :  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
      10             :  * sell copies of the Software, and to permit persons to whom the Software is
      11             :  * furnished to do so, subject to the following conditions:
      12             :  *
      13             :  * The above copyright notice and this permission notice shall be included in
      14             :  * all copies or substantial portions of the Software.
      15             :  *
      16             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      17             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      18             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      19             :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      20             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      21             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
      22             :  * IN THE SOFTWARE.
      23             :  */
      24             : 
      25             : #include <stdint.h>
      26             : #include <string.h>
      27             : 
      28             : #include "btctx.h"
      29             : #include "memutil.h"
      30             : 
      31             : #include "svarint.h"
      32             : 
      33             : // Context pointer
      34             : static btctx_ctx_t *ctx;
      35             : 
      36             : /*
      37             :  * Initialize the parser.
      38             :  *
      39             :  * @arg[in] ctx the context to be used for this session
      40             :  *          (should have its callback set)
      41             :  */
      42         375 : void btctx_init(btctx_ctx_t *_ctx, btctx_cb_t _cb) {
      43         375 :     ctx = _ctx;
      44         375 :     memset(ctx, 0, sizeof(btctx_ctx_t));
      45         375 :     ctx->state = BTCTX_ST_VERSION;
      46         375 :     ctx->callback = _cb;
      47         375 : }
      48             : 
      49             : /*
      50             :  * Tell whether parsing is finished, and
      51             :  * whether it triggered an error (and which one)
      52             :  * This should be checked after every call to btctx_consume
      53             :  */
      54      453026 : int8_t btctx_result() {
      55      453026 :     if (ctx->state < 0 || ctx->state == BTCTX_ST_DONE)
      56         736 :         return ctx->state;
      57      452290 :     return BTCTX_ERR_NONE;
      58             : }
      59             : 
      60             : /*
      61             :  * Consume a chunk of bytes.
      62             :  *
      63             :  * @arg[in] buf: buffer holding bytes to be consumed
      64             :  * @arg[in] len: number of bytes to consume in buffer
      65             :  *
      66             :  * @return the number of bytes actually read and processed
      67             :  */
      68      450572 : uint8_t btctx_consume(uint8_t *buf, const uint8_t len) {
      69             :     uint8_t processed;
      70             : 
      71     4476230 :     for (uint8_t i = 0; i < len; i++) {
      72     4026030 :         switch (ctx->state) {
      73        1496 :         case BTCTX_ST_VERSION:
      74             :             // Read little endian TX version
      75        1496 :             ctx->raw[ctx->offset] = buf[i];
      76        1496 :             ctx->parsed.version += (uint32_t)buf[i] << (8 * ctx->offset++);
      77        1496 :             if (ctx->offset == BTCTX_VERSION_SIZE) {
      78         374 :                 ctx->raw_size = BTCTX_VERSION_SIZE;
      79         374 :                 ctx->callback(BTCTX_EV_VERSION);
      80         372 :                 ctx->state = BTCTX_ST_VIN_COUNT;
      81         372 :                 svarint_init(&ctx->parsed.varint);
      82             :             }
      83        1494 :             break;
      84       27999 :         case BTCTX_ST_VIN_COUNT:
      85             :         case BTCTX_ST_VOUT_COUNT:
      86             :         case BTCTX_ST_VIN_SLENGTH:
      87             :         case BTCTX_ST_VOUT_SLENGTH:
      88       27999 :             if (svarint_notstarted())
      89       27954 :                 ctx->raw_size = 0;
      90       27999 :             processed = svarint_consume(buf + i, len - i);
      91       55998 :             SAFE_MEMMOVE(ctx->raw,
      92             :                          sizeof(ctx->raw),
      93             :                          ctx->raw_size,
      94             :                          buf,
      95             :                          len,
      96             :                          i,
      97             :                          processed,
      98             :                          {
      99             :                              ctx->state = BTCTX_ERR_INVALID;
     100             :                              return processed;
     101             :                          });
     102       27999 :             ctx->raw_size += processed;
     103       27999 :             i += processed - 1;
     104             : 
     105       27999 :             switch (svarint_result()) {
     106          45 :             case SVARINT_ERR_NONE:
     107          45 :                 break;
     108       27935 :             case SVARINT_ST_DONE:
     109       27935 :                 switch (ctx->state) {
     110         371 :                 case BTCTX_ST_VIN_COUNT:
     111         371 :                     ctx->callback(BTCTX_EV_VIN_COUNT);
     112         371 :                     ctx->inout_total = ctx->parsed.varint.value;
     113         371 :                     ctx->inout_current = 0;
     114         371 :                     ctx->state = BTCTX_ST_VIN_TXH;
     115         371 :                     ctx->offset = 0;
     116         371 :                     break;
     117         356 :                 case BTCTX_ST_VOUT_COUNT:
     118         356 :                     ctx->callback(BTCTX_EV_VOUT_COUNT);
     119         356 :                     ctx->inout_total = ctx->parsed.varint.value;
     120         356 :                     ctx->inout_current = 0;
     121         356 :                     ctx->state = BTCTX_ST_VOUT_VALUE;
     122         356 :                     ctx->offset = 0;
     123         356 :                     break;
     124       26299 :                 case BTCTX_ST_VIN_SLENGTH:
     125       26299 :                     ctx->callback(BTCTX_EV_VIN_SLENGTH);
     126       26299 :                     ctx->state = BTCTX_ST_VIN_SCRIPT;
     127       26299 :                     ctx->script_remaining = ctx->parsed.varint.value;
     128       26299 :                     break;
     129         909 :                 case BTCTX_ST_VOUT_SLENGTH:
     130         909 :                     ctx->callback(BTCTX_EV_VOUT_SLENGTH);
     131         909 :                     ctx->state = BTCTX_ST_VOUT_SCRIPT;
     132         909 :                     ctx->script_remaining = ctx->parsed.varint.value;
     133         909 :                     break;
     134             :                 }
     135       27935 :                 break;
     136          19 :             case SVARINT_ERR_UNSUPPORTED:
     137          19 :                 ctx->state = BTCTX_ERR_UNSUPPORTED;
     138          19 :                 return i + 1;
     139           0 :             case SVARINT_ERR_INVALID:
     140             :             default:
     141           0 :                 ctx->state = BTCTX_ERR_INVALID;
     142           0 :                 return i + 1;
     143             :             }
     144             : 
     145       27980 :             break;
     146      841728 :         case BTCTX_ST_VIN_TXH:
     147      841728 :             if (ctx->offset == 0) {
     148       26304 :                 ctx->raw_size = 0;
     149       26304 :                 ctx->callback(BTCTX_EV_VIN_TXH_START);
     150             :             }
     151      841728 :             ctx->parsed.value = ctx->raw[0] = buf[i];
     152      841728 :             ctx->raw_size = 1;
     153      841728 :             ctx->callback(BTCTX_EV_VIN_TXH_DATA);
     154      841728 :             if (++ctx->offset == BTCTX_HASH_SIZE) {
     155       26304 :                 ctx->raw_size = 0;
     156       26304 :                 ctx->callback(BTCTX_EV_VIN_TXH_END);
     157       26304 :                 ctx->state = BTCTX_ST_VIN_TXIX;
     158       26304 :                 ctx->offset = 0;
     159             :             }
     160      841728 :             break;
     161      105216 :         case BTCTX_ST_VIN_TXIX:
     162      105216 :             if (ctx->offset == 0)
     163       26304 :                 ctx->parsed.ptxo_index = 0;
     164      105216 :             ctx->raw[ctx->offset] = buf[i];
     165      105216 :             ctx->parsed.ptxo_index += (uint32_t)buf[i] << (8 * ctx->offset++);
     166      105216 :             if (ctx->offset == BTCTX_INPUT_INDEX_SIZE) {
     167       26304 :                 ctx->raw_size = BTCTX_INPUT_INDEX_SIZE;
     168       26304 :                 ctx->callback(BTCTX_EV_VIN_TXIX);
     169       26304 :                 ctx->state = BTCTX_ST_VIN_SLENGTH;
     170       26304 :                 svarint_init(&ctx->parsed.varint);
     171             :             }
     172      105216 :             break;
     173     2935687 :         case BTCTX_ST_VIN_SCRIPT:
     174             :         case BTCTX_ST_VOUT_SCRIPT:
     175     2935687 :             ctx->parsed.value = ctx->raw[0] = buf[i];
     176     2935687 :             ctx->raw_size = 1;
     177     2935687 :             ctx->script_remaining--;
     178     2935687 :             ctx->callback(ctx->state == BTCTX_ST_VIN_SCRIPT
     179             :                               ? BTCTX_EV_VIN_SCRIPT_DATA
     180             :                               : BTCTX_EV_VOUT_SCRIPT_DATA);
     181     2935685 :             if (ctx->script_remaining == 0) {
     182       27204 :                 if (ctx->state == BTCTX_ST_VIN_SCRIPT) {
     183       26295 :                     ctx->state = BTCTX_ST_VIN_SEQNO;
     184             :                 } else {
     185         909 :                     ctx->state = ++ctx->inout_current == ctx->inout_total
     186             :                                      ? BTCTX_ST_LOCK_TIME
     187             :                                      : BTCTX_ST_VOUT_VALUE;
     188             :                 }
     189       27204 :                 ctx->offset = 0;
     190             :             }
     191     2935685 :             break;
     192      105180 :         case BTCTX_ST_VIN_SEQNO:
     193      105180 :             if (ctx->offset == 0)
     194       26295 :                 ctx->parsed.seqno = 0;
     195      105180 :             ctx->raw[ctx->offset] = buf[i];
     196      105180 :             ctx->parsed.seqno += (uint32_t)buf[i] << (8 * ctx->offset++);
     197      105180 :             if (ctx->offset == BTCTX_INPUT_SEQNO_SIZE) {
     198       26295 :                 ctx->raw_size = BTCTX_INPUT_SEQNO_SIZE;
     199       26295 :                 ctx->callback(BTCTX_EV_VIN_SEQNO);
     200       26295 :                 if (++ctx->inout_current == ctx->inout_total) {
     201         362 :                     ctx->state = BTCTX_ST_VOUT_COUNT;
     202         362 :                     svarint_init(&ctx->parsed.varint);
     203             :                 } else {
     204       25933 :                     ctx->state = BTCTX_ST_VIN_TXH;
     205       25933 :                     ctx->offset = 0;
     206             :                 }
     207             :             }
     208      105180 :             break;
     209        7328 :         case BTCTX_ST_VOUT_VALUE:
     210        7328 :             if (ctx->offset == 0)
     211         916 :                 ctx->parsed.vout_value = 0L;
     212        7328 :             ctx->raw[ctx->offset] = buf[i];
     213        7328 :             ctx->parsed.vout_value += (uint64_t)buf[i] << 8 * ctx->offset++;
     214        7328 :             if (ctx->offset == BTCTX_OUTPUT_VALUE_SIZE) {
     215         916 :                 ctx->raw_size = BTCTX_OUTPUT_VALUE_SIZE;
     216         916 :                 ctx->callback(BTCTX_EV_VOUT_VALUE);
     217         916 :                 ctx->state = BTCTX_ST_VOUT_SLENGTH;
     218         916 :                 svarint_init(&ctx->parsed.varint);
     219             :             }
     220        7328 :             break;
     221        1396 :         case BTCTX_ST_LOCK_TIME:
     222        1396 :             if (ctx->offset == 0)
     223         349 :                 ctx->parsed.locktime = 0;
     224        1396 :             ctx->raw[ctx->offset] = buf[i];
     225        1396 :             ctx->parsed.locktime += (uint32_t)buf[i] << (8 * ctx->offset++);
     226        1396 :             if (ctx->offset == BTCTX_LOCKTIME_SIZE) {
     227         349 :                 ctx->raw_size = BTCTX_LOCKTIME_SIZE;
     228         349 :                 ctx->callback(BTCTX_EV_LOCKTIME);
     229         349 :                 ctx->state = BTCTX_ST_DONE;
     230         349 :                 return i + 1;
     231             :             }
     232        1047 :             break;
     233           0 :         default:
     234           0 :             return 0;
     235             :         }
     236             :     }
     237             : 
     238      450200 :     return len;
     239             : }

Generated by: LCOV version 1.16