pgp_export_keydata, pgp_import_keydata
authorEdouard Tisserant
Wed, 29 Apr 2015 01:00:59 +0200
changeset 2284e6728cddb3f
parent 227 9321f8fb77c2
child 229 313d152239bf
pgp_export_keydata, pgp_import_keydata
src/pgp_netpgp.c
     1.1 --- a/src/pgp_netpgp.c	Tue Apr 28 01:52:09 2015 +0200
     1.2 +++ b/src/pgp_netpgp.c	Wed Apr 29 01:00:59 2015 +0200
     1.3 @@ -11,6 +11,7 @@
     1.4  #include <netpgp/crypto.h>
     1.5  #include <netpgp/netpgpsdk.h>
     1.6  #include <netpgp/validate.h>
     1.7 +#include <netpgp/readerwriter.h>
     1.8  
     1.9  #include <regex.h>
    1.10  
    1.11 @@ -482,7 +483,6 @@
    1.12  
    1.13          char *_buffer = NULL;
    1.14          size_t length = pgp_mem_len(cmem);
    1.15 -        assert(length != -1);
    1.16  
    1.17          // Allocate transferable buffer
    1.18          _buffer = malloc(length + 1);
    1.19 @@ -514,8 +514,8 @@
    1.20  static unsigned
    1.21  fpr_to_str (char **str, const uint8_t *fpr, size_t length)
    1.22  {
    1.23 -	unsigned i;
    1.24 -	int	n;
    1.25 +    unsigned i;
    1.26 +    int	n;
    1.27  
    1.28      /* 5 char per byte (hexes + space) tuple -1 space at the end + null */
    1.29      *str = malloc((length / 2) * 5 - 1 + 1);
    1.30 @@ -523,12 +523,12 @@
    1.31      if(*str == NULL)
    1.32          return 0;
    1.33  
    1.34 -	for (n = 0, i = 0 ; i < length - 1; i += 2) {
    1.35 -		n += snprintf(&((*str)[n]), 6, "%02x%02x ", *fpr++, *fpr++);
    1.36 -	}
    1.37 +    for (n = 0, i = 0 ; i < length - 1; i += 2) {
    1.38 +    	n += snprintf(&((*str)[n]), 6, "%02x%02x ", *fpr++, *fpr++);
    1.39 +    }
    1.40      snprintf(&((*str)[n]), 5, "%02x%02x", *fpr++, *fpr++);
    1.41  
    1.42 -	return 1;
    1.43 +    return 1;
    1.44  }
    1.45  
    1.46  static unsigned
    1.47 @@ -561,18 +561,65 @@
    1.48      return 1;
    1.49  }
    1.50  
    1.51 +static PEP_STATUS import_key_or_keypair(netpgp_t *netpgp, pgp_key_t *newkey){
    1.52 +    pgp_key_t	pubkey;
    1.53 +    unsigned public;
    1.54 +    PEP_STATUS result;
    1.55 +
    1.56 +    if ((public = (newkey->type == PGP_PTAG_CT_PUBLIC_KEY))){
    1.57 +        pubkey = *newkey;
    1.58 +    } else {
    1.59 +        // Duplicate key as public only
    1.60 +        if (!pgp_keydata_dup(&pubkey, newkey, 1 /* make_public */)){
    1.61 +            return PEP_OUT_OF_MEMORY;
    1.62 +        }
    1.63 +    }
    1.64 +
    1.65 +    // Append generated key to netpgp's rings (key ownership transfered)
    1.66 +    if (!public && !pgp_keyring_add(netpgp->secring, newkey)){
    1.67 +        result = PEP_OUT_OF_MEMORY;
    1.68 +        goto free_pubkey;
    1.69 +    } else if (!pgp_keyring_add(netpgp->pubring, &pubkey)){
    1.70 +        result = PEP_OUT_OF_MEMORY;
    1.71 +        goto pop_secring;
    1.72 +    }
    1.73 +
    1.74 +    // save rings 
    1.75 +    if (netpgp_save_pubring(netpgp) && 
    1.76 +        (!public || netpgp_save_secring(netpgp)))
    1.77 +    {
    1.78 +        /* free nothing, everything transfered */
    1.79 +        return PEP_STATUS_OK;
    1.80 +    } else {
    1.81 +        /* XXX in case only pubring save succeed
    1.82 +         * pubring file is left as-is, but backup restore
    1.83 +         * could be attempted if such corner case matters */
    1.84 +        result = PEP_UNKNOWN_ERROR;
    1.85 +    }
    1.86 +
    1.87 +pop_pubring:
    1.88 +    ((pgp_keyring_t *)netpgp->pubring)->keyc--;
    1.89 +pop_secring:
    1.90 +    ((pgp_keyring_t *)netpgp->secring)->keyc--;
    1.91 +free_pubkey:
    1.92 +    pgp_key_free(&pubkey);
    1.93 +
    1.94 +    return result;
    1.95 +}
    1.96 +
    1.97  PEP_STATUS pgp_generate_keypair(
    1.98      PEP_SESSION session, pEp_identity *identity
    1.99      )
   1.100  {
   1.101      netpgp_t *netpgp;
   1.102 -	pgp_key_t	newkey;
   1.103 -	pgp_key_t	pubkey;
   1.104 +    pgp_key_t	newkey;
   1.105 +    pgp_key_t	pubkey;
   1.106  
   1.107      PEP_STATUS result;
   1.108 -	char newid[1024];
   1.109 +    char newid[1024];
   1.110      const char *hashalg;
   1.111      const char *cipher;
   1.112 +    char *fprstr = NULL;
   1.113  
   1.114      assert(session);
   1.115      assert(identity);
   1.116 @@ -600,38 +647,34 @@
   1.117      // Generate the key
   1.118      if (!pgp_rsa_generate_keypair(&newkey, 4096, 65537UL, hashalg, cipher,
   1.119                                    (const uint8_t *) "", (const size_t) 0) ||
   1.120 -        !pgp_add_selfsigned_userid(&newkey, (const uint8_t *)newid)) {
   1.121 -        return PEP_CANNOT_CREATE_KEY;
   1.122 -	}
   1.123 +        !pgp_add_selfsigned_userid(&newkey, (uint8_t *)newid)) {
   1.124 +        result = PEP_CANNOT_CREATE_KEY;
   1.125 +        goto free_newkey;
   1.126 +    }
   1.127  
   1.128      // TODO "Expire-Date: 1y\n";
   1.129  
   1.130 -    // Duplicate key as public only
   1.131 -    pgp_keydata_dup(&pubkey, &newkey, 1 /* make_public */);
   1.132 +    fpr_to_str(&fprstr,
   1.133 +               newkey.sigfingerprint.fingerprint,
   1.134 +               newkey.sigfingerprint.length);
   1.135 +    if (fprstr == NULL) {
   1.136 +        result = PEP_OUT_OF_MEMORY;
   1.137 +        goto free_newkey;
   1.138 +    } 
   1.139  
   1.140 -    // Append generated key to netpgp's rings
   1.141 -    pgp_keyring_add(netpgp->secring, &newkey);
   1.142 -    pgp_keyring_add(netpgp->pubring, &pubkey);
   1.143 -    // FIXME doesn't check result since always true 
   1.144 -    // TODO alloc error feedback in netpgp
   1.145 +    result = import_key_or_keypair(netpgp, &newkey);
   1.146  
   1.147 -    // save rings (key ownership transfered)
   1.148 -    if (netpgp_save_pubring(netpgp) && 
   1.149 -        netpgp_save_secring(netpgp))
   1.150 -    {
   1.151 -        char *fprstr = NULL;
   1.152 -        fpr_to_str(&fprstr,
   1.153 -                   newkey.sigfingerprint.fingerprint,
   1.154 -                   newkey.sigfingerprint.length);
   1.155 -        if ((identity->fpr = fprstr) == NULL) {
   1.156 -            result = PEP_OUT_OF_MEMORY;
   1.157 -        }else{
   1.158 -            result = PEP_STATUS_OK;
   1.159 -        }
   1.160 -    }else{
   1.161 -        result = PEP_UNKNOWN_ERROR;
   1.162 +    if (result == PEP_STATUS_OK) {
   1.163 +        identity->fpr = fprstr;
   1.164 +        /* free nothing, everything transfered */
   1.165 +        return PEP_STATUS_OK;
   1.166      }
   1.167  
   1.168 +free_fprstr:
   1.169 +    free(fprstr);
   1.170 +free_newkey:
   1.171 +    pgp_key_free(&newkey);
   1.172 +
   1.173      return result;
   1.174  }
   1.175  
   1.176 @@ -654,8 +697,8 @@
   1.177      
   1.178      if (str_to_fpr(fprstr, fpr, &length)) {
   1.179          if (!pgp_deletekeybyfpr(netpgp->io,
   1.180 -                                (pgp_pubkey_t *)netpgp->secring, 
   1.181 -                                fpr, length)) {
   1.182 +                                (pgp_keyring_t *)netpgp->secring, 
   1.183 +                                (const uint8_t *)fpr, length)) {
   1.184              return PEP_KEY_NOT_FOUND;
   1.185          }
   1.186      }else{
   1.187 @@ -666,8 +709,8 @@
   1.188       * in pubring if it exists */
   1.189      if(res) {
   1.190          pgp_deletekeybyfpr(netpgp->io,
   1.191 -                           (pgp_pubkey_t *)netpgp->pubring, 
   1.192 -                           fpr, length);
   1.193 +                           (pgp_keyring_t *)netpgp->pubring, 
   1.194 +                           (const uint8_t *)fpr, length);
   1.195      }
   1.196  
   1.197      // save rings (key ownership transfered)
   1.198 @@ -682,54 +725,121 @@
   1.199      return result;
   1.200  }
   1.201  
   1.202 +#define ARMOR_KEY_HEAD    "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----\\s*$"
   1.203  PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
   1.204  {
   1.205 +
   1.206 +    netpgp_t *netpgp;
   1.207 +    pgp_memory_t *mem;
   1.208 +    pgp_keyring_t tmpring;
   1.209 +
   1.210 +    PEP_STATUS result;
   1.211 +
   1.212      assert(session);
   1.213      assert(key_data);
   1.214  
   1.215 -    /* TODO import */
   1.216 +    if(!session || !key_data) 
   1.217          return PEP_UNKNOWN_ERROR;
   1.218 -        return PEP_ILLEGAL_VALUE;
   1.219 -        return PEP_UNKNOWN_ERROR;
   1.220 -    return PEP_STATUS_OK;
   1.221 +
   1.222 +    netpgp = &session->ctx;
   1.223 +
   1.224 +    mem = pgp_memory_new();
   1.225 +    if (mem == NULL) {
   1.226 +        return PEP_OUT_OF_MEMORY;
   1.227 +    }
   1.228 +    pgp_memory_add(mem, (const uint8_t*)key_data, size);
   1.229 +
   1.230 +    if (pgp_keyring_read_from_mem(netpgp->io, &tmpring, 
   1.231 +                                  _armoured(key_data, size, ARMOR_KEY_HEAD),
   1.232 +                                  mem) == 0){
   1.233 +        result = PEP_ILLEGAL_VALUE;
   1.234 +    }else if (tmpring.keyc == 0){
   1.235 +        result = PEP_UNKNOWN_ERROR;
   1.236 +    }else if (tmpring.keyc > 1){
   1.237 +        /* too many keys given */
   1.238 +        result = PEP_ILLEGAL_VALUE;
   1.239 +    }else{
   1.240 +        result = import_key_or_keypair(netpgp, &tmpring.keys[0]);
   1.241 +    }
   1.242 +    
   1.243 +    pgp_memory_free(mem);
   1.244 +
   1.245 +    if (result != PEP_STATUS_OK){
   1.246 +        pgp_keyring_purge(&tmpring);
   1.247 +    }
   1.248 +
   1.249 +    return result;
   1.250  }
   1.251  
   1.252  PEP_STATUS pgp_export_keydata(
   1.253 -    PEP_SESSION session, const char *fpr, char **key_data, size_t *size
   1.254 +    PEP_SESSION session, const char *fprstr, char **key_data, size_t *size
   1.255      )
   1.256  {
   1.257 -    size_t _size;
   1.258 +    netpgp_t *netpgp;
   1.259 +    pgp_key_t *key;
   1.260 +	pgp_output_t *output;
   1.261 +    pgp_memory_t *mem;
   1.262 +    uint8_t fpr[PGP_FINGERPRINT_SIZE];
   1.263 +    size_t fprlen;
   1.264 +
   1.265 +    PEP_STATUS result;
   1.266      char *buffer;
   1.267 -    int reading;
   1.268 +    size_t buflen;
   1.269  
   1.270      assert(session);
   1.271      assert(fpr);
   1.272      assert(key_data);
   1.273      assert(size);
   1.274  
   1.275 +    netpgp = &session->ctx;
   1.276  
   1.277 -    /* TODO export */
   1.278 -        return PEP_KEY_NOT_FOUND;
   1.279 -        return PEP_UNKNOWN_ERROR;
   1.280 +    if (!session || !fpr || !key_data || !size)
   1.281          return PEP_UNKNOWN_ERROR;
   1.282  
   1.283 -    _size = /* TODO */ 0;
   1.284 -    assert(_size != -1);
   1.285 +    if (str_to_fpr(fprstr, fpr, &fprlen)) {
   1.286 +        unsigned from = 0;
   1.287 +        if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, netpgp->pubring, 
   1.288 +                                                fpr, fprlen,
   1.289 +                                                &from, NULL)) == NULL) {
   1.290 +            return PEP_KEY_NOT_FOUND;
   1.291 +        }
   1.292 +    }else{
   1.293 +        return PEP_OUT_OF_MEMORY;
   1.294 +    }
   1.295 +    
   1.296 +	pgp_setup_memory_write(&output, &mem, 128);
   1.297  
   1.298 -    buffer = malloc(_size + 1);
   1.299 -    assert(buffer);
   1.300 -    if (buffer == NULL) {
   1.301 -        /* TODO clean */
   1.302 +    if (mem == NULL || output == NULL) {
   1.303          return PEP_OUT_OF_MEMORY;
   1.304      }
   1.305  
   1.306 -    // safeguard for the naive user
   1.307 -    buffer[_size] = 0;
   1.308 +    if (!pgp_write_xfer_pubkey(output, key, 1)) {
   1.309 +        result = PEP_UNKNOWN_ERROR;
   1.310 +        goto free_mem;
   1.311 +    }
   1.312 +
   1.313 +    buffer = NULL;
   1.314 +    buflen = pgp_mem_len(mem);
   1.315 +
   1.316 +    // Allocate transferable buffer
   1.317 +    buffer = malloc(buflen + 1);
   1.318 +    assert(buffer);
   1.319 +    if (buffer == NULL) {
   1.320 +        result = PEP_OUT_OF_MEMORY;
   1.321 +        goto free_mem;
   1.322 +    }
   1.323 +
   1.324 +    memcpy(buffer, pgp_mem_data(mem), buflen);
   1.325  
   1.326      *key_data = buffer;
   1.327 -    *size = _size;
   1.328 +    *size = buflen;
   1.329 +    (*key_data)[*size] = 0; // safeguard for naive users
   1.330 +    result = PEP_STATUS_OK;
   1.331  
   1.332 -    return PEP_STATUS_OK;
   1.333 +free_mem :
   1.334 +	pgp_teardown_memory_write(output, mem);
   1.335 +
   1.336 +    return result;
   1.337  }
   1.338  
   1.339  // "keyserver"