supercop

Basic CLI for supercop
git clone git://git.finwo.net/app/supercop
Log | Files | Refs | README | LICENSE

decode.c (2670B)


      1 #include <stdlib.h>
      2 #include <string.h>
      3 
      4 #include "common.h"
      5 #include "scan.h"
      6 #include "orlp/ed25519.h"
      7 
      8 #ifdef __cplusplus
      9 extern "C" {
     10 #endif
     11 
     12 static int hdr_hexval(unsigned char c) {
     13   if (c >= '0' && c <= '9') return c - '0';
     14   if (c >= 'a' && c <= 'f') return c - 'a' + 10;
     15   if (c >= 'A' && c <= 'F') return c - 'A' + 10;
     16   return -1;
     17 }
     18 
     19 // Parse exactly hexlen hex chars into out; returns 1 on success.
     20 static int hdr_parse_hex(const unsigned char *val, size_t vallen,
     21                          unsigned char *out, size_t hexlen) {
     22   size_t i;
     23   int hi, lo;
     24   if (vallen != hexlen * 2) return 0;
     25   for (i = 0; i < hexlen; i++) {
     26     hi = hdr_hexval(val[i * 2]);
     27     lo = hdr_hexval(val[i * 2 + 1]);
     28     if (hi < 0 || lo < 0) return 0;
     29     out[i] = (unsigned char)((hi << 4) | lo);
     30   }
     31   return 1;
     32 }
     33 
     34 struct KeyPair * fmt_hdr_decode(unsigned char *cipherdata, size_t len) {
     35   const unsigned char *pos = cipherdata;
     36   const unsigned char *end = cipherdata + len;
     37   const unsigned char *line;
     38   size_t linelen;
     39   int which;
     40   const unsigned char *val;
     41   size_t vallen;
     42   unsigned char pub[32];
     43   unsigned char priv[64];
     44   int seen_pub = 0, have_pub = 0;
     45   int seen_priv = 0, have_priv = 0;
     46   struct KeyPair *kp;
     47 
     48   // First valid occurrence of each label wins; malformed hex runs are
     49   // ignored so a later valid block in the stream can still win.
     50   while (hdr_next_line(&pos, end, &line, &linelen)) {
     51     if (!hdr_match_label(line, linelen, &which, &val, &vallen)) continue;
     52     if (which == 1 && seen_pub) continue;
     53     if (which == 2 && seen_priv) continue;
     54     if (vallen == 0) continue;
     55     // Parenthesized value marks the field absent (e.g. "(no private key)")
     56     if (val[0] == '(') {
     57       if (which == 1) seen_pub = 1;
     58       else seen_priv = 1;
     59       continue;
     60     }
     61     if (which == 1) {
     62       if (!hdr_parse_hex(val, vallen, pub, 32)) continue;
     63       seen_pub = 1;
     64       have_pub = 1;
     65     } else {
     66       if (!hdr_parse_hex(val, vallen, priv, 64)) continue;
     67       seen_priv = 1;
     68       have_priv = 1;
     69     }
     70   }
     71 
     72   if (!have_pub && !have_priv) return NULL;
     73 
     74   // A lone private key still yields its public half via scalar mult
     75   if (!have_pub) {
     76     ed25519_derive_pubkey(pub, priv);
     77     have_pub = 1;
     78   }
     79 
     80   kp = calloc(1, sizeof(struct KeyPair));
     81   if (!kp) return NULL;
     82   kp->public_key = calloc(1, 32);
     83   if (!kp->public_key) {
     84     free(kp);
     85     return NULL;
     86   }
     87   memcpy(kp->public_key, pub, 32);
     88   if (have_priv) {
     89     kp->private_key = calloc(1, 64);
     90     if (!kp->private_key) {
     91       free(kp->public_key);
     92       free(kp);
     93       return NULL;
     94     }
     95     memcpy(kp->private_key, priv, 64);
     96   }
     97   return kp;
     98 }
     99 
    100 #ifdef __cplusplus
    101 } // extern "C"
    102 #endif