netpgp : pgp_verify_text implemented. need more fixing in netpgp
authorEdouard Tisserant
Sat, 11 Apr 2015 18:22:33 +0200
changeset 185f3142e40d9e7
parent 184 da3973ecb7b6
child 186 cfd6fe0e9dc5
netpgp : pgp_verify_text implemented. need more fixing in netpgp
src/pgp_netpgp.c
test/pEpEngineTest.cc
     1.1 --- a/src/pgp_netpgp.c	Wed Apr 08 22:51:03 2015 +0200
     1.2 +++ b/src/pgp_netpgp.c	Sat Apr 11 18:22:33 2015 +0200
     1.3 @@ -12,6 +12,8 @@
     1.4  #include <netpgp/netpgpsdk.h>
     1.5  #include <netpgp/validate.h>
     1.6  
     1.7 +#define PEP_NETPGP_DEBUG
     1.8 +
     1.9  PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
    1.10  {
    1.11      netpgp_t *netpgp;
    1.12 @@ -28,7 +30,7 @@
    1.13              setlocale(LC_ALL, "");
    1.14      }
    1.15  
    1.16 -	memset(netpgp, 0x0, sizeof(session->ctx));
    1.17 +    memset(netpgp, 0x0, sizeof(session->ctx));
    1.18  
    1.19      // netpgp_setvar(netpgp, "max mem alloc", "4194304");
    1.20      netpgp_setvar(netpgp, "need seckey", "1");
    1.21 @@ -44,13 +46,13 @@
    1.22      }
    1.23  
    1.24      // pair with gpg's cert-digest-algo
    1.25 -	netpgp_setvar(netpgp, "hash", "SHA256");
    1.26 +    netpgp_setvar(netpgp, "hash", "SHA256");
    1.27  
    1.28      // subset of gpg's personal-cipher-preferences
    1.29      // here only one cipher can be selected
    1.30      netpgp_setvar(netpgp, "cipher", "AES256");
    1.31  
    1.32 -	if (!netpgp_init(netpgp)) {
    1.33 +    if (!netpgp_init(netpgp)) {
    1.34          status = PEP_INIT_NETPGP_INIT_FAILED;
    1.35          goto pep_error;
    1.36      }
    1.37 @@ -71,25 +73,127 @@
    1.38  
    1.39      netpgp = &session->ctx;
    1.40  
    1.41 -	netpgp_end(netpgp);
    1.42 -	memset(netpgp, 0x0, sizeof(session->ctx));
    1.43 +    netpgp_end(netpgp);
    1.44 +    memset(netpgp, 0x0, sizeof(session->ctx));
    1.45  
    1.46      // out_last unused here
    1.47  }
    1.48  
    1.49 +// Iterate through netpgp' reported valid signatures 
    1.50 +// fill a list of valid figerprints
    1.51 +// returns PEP_STATUS_OK if all sig reported valid
    1.52 +// error status otherwise.
    1.53 +static PEP_STATUS _validation_results(netpgp_t *netpgp, pgp_validation_t *vresult,
    1.54 +                                             stringlist_t **_keylist)
    1.55 +{
    1.56 +	time_t	now;
    1.57 +	time_t	t;
    1.58 +	char	buf[128];
    1.59 +
    1.60 +	now = time(NULL);
    1.61 +	if (now < vresult->birthtime) {
    1.62 +		// signature is not valid yet
    1.63 +#ifdef PEP_NETPGP_DEBUG
    1.64 +		(void) printf(
    1.65 +			"signature not valid until %.24s\n",
    1.66 +			ctime(&vresult->birthtime));
    1.67 +#endif //PEP_NETPGP_DEBUG
    1.68 +		return PEP_UNENCRYPTED;
    1.69 +	}
    1.70 +	if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) {
    1.71 +		// signature has expired
    1.72 +		t = vresult->duration + vresult->birthtime;
    1.73 +#ifdef PEP_NETPGP_DEBUG
    1.74 +		(void) printf(
    1.75 +			"signature not valid after %.24s\n",
    1.76 +			ctime(&t));
    1.77 +#endif //PEP_NETPGP_DEBUG
    1.78 +		return PEP_UNENCRYPTED;
    1.79 +	}
    1.80 +    if (vresult->validc && vresult->valid_sigs &&
    1.81 +        !vresult->invalidc && !vresult->unknownc ) {
    1.82 +        unsigned    n;
    1.83 +        stringlist_t *k;
    1.84 +        // caller responsible to free
    1.85 +        *_keylist = new_stringlist(NULL);
    1.86 +        assert(*_keylist);
    1.87 +        if (*_keylist == NULL) {
    1.88 +            return PEP_OUT_OF_MEMORY;
    1.89 +        }
    1.90 +        k = *_keylist;
    1.91 +        for (n = 0; n < vresult->validc; ++n) {
    1.92 +            int i;
    1.93 +            char id[MAX_ID_LENGTH + 1];
    1.94 +            static const char *hexes = "0123456789abcdef";
    1.95 +            const uint8_t *userid = vresult->valid_sigs[n].signer_id;
    1.96 +
    1.97 +#ifdef PEP_NETPGP_DEBUG
    1.98 +            const pgp_key_t *key;
    1.99 +            pgp_pubkey_t *sigkey;
   1.100 +	        unsigned from = 0;
   1.101 +            key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
   1.102 +                (const uint8_t *) vresult->valid_sigs[n].signer_id,
   1.103 +                &from, &sigkey);
   1.104 +            pgp_print_keydata(netpgp->io, netpgp->pubring, key, "valid signature ", &key->key.pubkey, 0);
   1.105 +#endif //PEP_NETPGP_DEBUG
   1.106 +
   1.107 +            for (i = 0; i < 8 ; i++) {
   1.108 +                id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
   1.109 +                id[(i * 2) + 1] = hexes[userid[i] & 0xf];
   1.110 +            }
   1.111 +            id[8 * 2] = 0x0;
   1.112 +
   1.113 +            k = stringlist_add(k, id);
   1.114 +            if(!k){
   1.115 +                free_stringlist(*_keylist);
   1.116 +                return PEP_OUT_OF_MEMORY;
   1.117 +            }
   1.118 +        }
   1.119 +        return PEP_STATUS_OK;
   1.120 +    }
   1.121 +    if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
   1.122 +        // No signatures found - is this memory signed?
   1.123 +        return PEP_VERIFY_NO_KEY; 
   1.124 +    } 
   1.125 +    
   1.126 +    if (vresult->invalidc) {
   1.127 +        // some invalid signatures
   1.128 +
   1.129 +#ifdef PEP_NETPGP_DEBUG
   1.130 +        unsigned    n;
   1.131 +        for (n = 0; n < vresult->invalidc; ++n) {
   1.132 +            const pgp_key_t *key;
   1.133 +            pgp_pubkey_t *sigkey;
   1.134 +            unsigned from = 0;
   1.135 +            key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
   1.136 +                (const uint8_t *) vresult->invalid_sigs[n].signer_id,
   1.137 +                &from, &sigkey);
   1.138 +            pgp_print_keydata(netpgp->io, netpgp->pubring, key, "invalid signature ", &key->key.pubkey, 0);
   1.139 +	        if (sigkey->duration != 0 && now > sigkey->birthtime + sigkey->duration) {
   1.140 +                printf("EXPIRED !\n");
   1.141 +            }
   1.142 +        }
   1.143 +#endif //PEP_NETPGP_DEBUG
   1.144 +
   1.145 +        return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   1.146 +    }
   1.147 +    
   1.148 +    // only unknown sigs
   1.149 +    return PEP_DECRYPT_WRONG_FORMAT;
   1.150 +}
   1.151 +
   1.152  PEP_STATUS pgp_decrypt_and_verify(
   1.153      PEP_SESSION session, const char *ctext, size_t csize,
   1.154      char **ptext, size_t *psize, stringlist_t **keylist
   1.155      )
   1.156  {
   1.157      netpgp_t *netpgp;
   1.158 -	pgp_memory_t *mem;
   1.159 -	pgp_memory_t *cat;
   1.160 -	pgp_validation_t *vresult;
   1.161 -	pgp_io_t *io;
   1.162 +    pgp_memory_t *mem;
   1.163 +    pgp_memory_t *cat;
   1.164 +    pgp_validation_t *vresult;
   1.165      char *_ptext = NULL;
   1.166      size_t _psize = 0;
   1.167 -	int ret;
   1.168 +    int ret;
   1.169  
   1.170      PEP_STATUS result;
   1.171      stringlist_t *_keylist = NULL;
   1.172 @@ -106,14 +210,13 @@
   1.173          return PEP_UNKNOWN_ERROR;
   1.174  
   1.175      netpgp = &session->ctx;
   1.176 -	io = netpgp->io;
   1.177  
   1.178      *ptext = NULL;
   1.179      *psize = 0;
   1.180      *keylist = NULL;
   1.181  
   1.182      vresult = malloc(sizeof(pgp_validation_t));
   1.183 -	memset(vresult, 0x0, sizeof(pgp_validation_t));
   1.184 +    memset(vresult, 0x0, sizeof(pgp_validation_t));
   1.185  
   1.186      mem = pgp_decrypt_and_validate_buf(netpgp->io, vresult, ctext, csize,
   1.187                  netpgp->secring, netpgp->pubring,
   1.188 @@ -124,60 +227,25 @@
   1.189          return PEP_OUT_OF_MEMORY;
   1.190      }
   1.191  
   1.192 -	_psize = pgp_mem_len(mem);
   1.193 +    _psize = pgp_mem_len(mem);
   1.194      if (_psize){
   1.195          if ((_ptext = calloc(1, _psize)) == NULL) {
   1.196              result = PEP_OUT_OF_MEMORY;
   1.197              goto free_pgp;
   1.198          }
   1.199 -	    memcpy(_ptext, pgp_mem_data(mem), _psize);
   1.200 +        memcpy(_ptext, pgp_mem_data(mem), _psize);
   1.201          result = PEP_DECRYPTED;
   1.202      }else{
   1.203          result = PEP_DECRYPT_NO_KEY;
   1.204          goto free_pgp;
   1.205      }
   1.206  
   1.207 -    if (result == PEP_DECRYPTED &&
   1.208 -        vresult->validc && vresult->valid_sigs &&
   1.209 -        !vresult->invalidc && !vresult->unknownc ) {
   1.210 -        unsigned	n;
   1.211 -        stringlist_t *k;
   1.212 -        _keylist = new_stringlist(NULL);
   1.213 -        assert(_keylist);
   1.214 -        if (_keylist == NULL) {
   1.215 -            result = PEP_OUT_OF_MEMORY;
   1.216 -            goto free_keylist;
   1.217 -        }
   1.218 -        k = _keylist;
   1.219 -        for (n = 0; n < vresult->validc; ++n) {
   1.220 -            int i;
   1.221 -            static const char *hexes = "0123456789abcdef";
   1.222 -            char id[MAX_ID_LENGTH + 1];
   1.223 -            const uint8_t *userid = vresult->valid_sigs[n].signer_id;
   1.224 -
   1.225 -            for (i = 0; i < 8 ; i++) {
   1.226 -                id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
   1.227 -                id[(i * 2) + 1] = hexes[userid[i] & 0xf];
   1.228 -            }
   1.229 -            id[8 * 2] = 0x0;
   1.230 -            k = stringlist_add(k, id);
   1.231 +    if (result == PEP_DECRYPTED) {
   1.232 +        result = _validation_results(netpgp, vresult, &_keylist);
   1.233 +        if (result != PEP_STATUS_OK) {
   1.234 +            goto free_ptext;
   1.235          }
   1.236          result = PEP_DECRYPTED_AND_VERIFIED;
   1.237 -	}else{
   1.238 -        if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
   1.239 -            // No signatures found - is this memory signed?
   1.240 -            result = PEP_VERIFY_NO_KEY; 
   1.241 -            goto free_ptext;
   1.242 -        } else if (vresult->invalidc) {
   1.243 -            // invalid memory
   1.244 -            result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   1.245 -            goto free_ptext;
   1.246 -        } else {
   1.247 -            // only unknown sigs
   1.248 -            // or valid sig not provided in result
   1.249 -            result = PEP_DECRYPT_WRONG_FORMAT;
   1.250 -            goto free_ptext;
   1.251 -        }
   1.252      }
   1.253  
   1.254      if (result == PEP_DECRYPTED_AND_VERIFIED
   1.255 @@ -185,7 +253,9 @@
   1.256          *ptext = _ptext;
   1.257          *psize = _psize;
   1.258          (*ptext)[*psize] = 0; // safeguard for naive users
   1.259 -        *keylist = _keylist;
   1.260 +        if (result == PEP_DECRYPTED_AND_VERIFIED) {
   1.261 +            *keylist = _keylist;
   1.262 +        }
   1.263  
   1.264          /* _ptext and _keylist ownership transfer, don't free */
   1.265          goto free_pgp;
   1.266 @@ -198,7 +268,7 @@
   1.267      free(_ptext);
   1.268  
   1.269  free_pgp:
   1.270 -	pgp_memory_free(mem);
   1.271 +    pgp_memory_free(mem);
   1.272      pgp_validate_result_free(vresult);
   1.273  
   1.274      return result;
   1.275 @@ -209,6 +279,12 @@
   1.276      const char *signature, size_t sig_size, stringlist_t **keylist
   1.277      )
   1.278  {
   1.279 +    netpgp_t *netpgp;
   1.280 +    pgp_memory_t *signedmem;
   1.281 +    pgp_memory_t *sig;
   1.282 +    pgp_validation_t *vresult;
   1.283 +    pgp_io_t *io;
   1.284 +
   1.285      PEP_STATUS result;
   1.286      stringlist_t *_keylist;
   1.287  
   1.288 @@ -219,21 +295,65 @@
   1.289      assert(sig_size);
   1.290      assert(keylist);
   1.291  
   1.292 +    if(!session || !text || !size || !signature || !sig_size || !keylist) 
   1.293 +        return PEP_UNKNOWN_ERROR;
   1.294 +
   1.295 +    netpgp = &session->ctx;
   1.296 +
   1.297      *keylist = NULL;
   1.298 -    /* if OK, verify */
   1.299 -            stringlist_t *k;
   1.300 -            k = _keylist;
   1.301 -            result = PEP_VERIFIED;
   1.302 -            do {
   1.303 -                k = stringlist_add(k, "TODO");
   1.304 -                if (k == NULL) {
   1.305 -                    free_stringlist(_keylist);
   1.306 -                    /* TODO */
   1.307 -                    return PEP_OUT_OF_MEMORY;
   1.308 -                }
   1.309 -            } while (0 /*TODO*/);
   1.310 -            *keylist = _keylist;
   1.311 -    /*
   1.312 +
   1.313 +    vresult = malloc(sizeof(pgp_validation_t));
   1.314 +    memset(vresult, 0x0, sizeof(pgp_validation_t));
   1.315 +
   1.316 +    signedmem = pgp_memory_new();
   1.317 +    if (signedmem == NULL) {
   1.318 +        return PEP_OUT_OF_MEMORY;
   1.319 +    }
   1.320 +    pgp_memory_add(signedmem, (const uint8_t*)text, size);
   1.321 +
   1.322 +    sig = pgp_memory_new();
   1.323 +    if (sig == NULL) {
   1.324 +        pgp_memory_free(signedmem);
   1.325 +        return PEP_OUT_OF_MEMORY;
   1.326 +    }
   1.327 +    pgp_memory_add(sig, (const uint8_t*)signature, sig_size);
   1.328 +
   1.329 +    pgp_validate_mem_detached(netpgp->io, vresult, sig,
   1.330 +                NULL,/* output */
   1.331 +                1,/* armored */
   1.332 +                netpgp->pubring,
   1.333 +                signedmem);
   1.334 +
   1.335 +    result = _validation_results(netpgp, vresult, &_keylist);
   1.336 +    if (result != PEP_STATUS_OK) {
   1.337 +        goto free_pgp;
   1.338 +    }else{
   1.339 +        result = PEP_VERIFIED;
   1.340 +    }
   1.341 +
   1.342 +    if (result == PEP_VERIFIED) {
   1.343 +        /* TODO : check trust level */
   1.344 +        result = PEP_VERIFIED_AND_TRUSTED;
   1.345 +    }
   1.346 +
   1.347 +    if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) {
   1.348 +        *keylist = _keylist;
   1.349 +
   1.350 +        /* _keylist ownership transfer, don't free */
   1.351 +        goto free_pgp;
   1.352 +    }
   1.353 +
   1.354 +free_keylist:
   1.355 +    free_stringlist(_keylist);
   1.356 +
   1.357 +free_pgp:
   1.358 +    // pgp_memory_free(sig) done by pgp_validate_mem - why ?
   1.359 +    pgp_memory_free(signedmem);
   1.360 +    pgp_validate_result_free(vresult);
   1.361 +
   1.362 +    return result;
   1.363 +
   1.364 +    /* TODO check
   1.365      result = PEP_UNENCRYPTED;
   1.366      result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   1.367      result = PEP_VERIFIED_AND_TRUSTED;
   1.368 @@ -242,9 +362,6 @@
   1.369      result = PEP_DECRYPT_WRONG_FORMAT;
   1.370      return PEP_OUT_OF_MEMORY;
   1.371      */
   1.372 -    result = PEP_UNKNOWN_ERROR;
   1.373 -
   1.374 -    return result;
   1.375  }
   1.376  
   1.377  PEP_STATUS pgp_encrypt_and_sign(
     2.1 --- a/test/pEpEngineTest.cc	Wed Apr 08 22:51:03 2015 +0200
     2.2 +++ b/test/pEpEngineTest.cc	Sat Apr 11 18:22:33 2015 +0200
     2.3 @@ -98,8 +98,9 @@
     2.4      size_t sig_length = 0;
     2.5      ReadFileIntoMem("signature.asc", sig_buffer, sig_length);
     2.6  
     2.7 -    cout << "\ncalling verify_test()\n";
     2.8 +    cout << "\ncalling verify_text()\n";
     2.9      PEP_STATUS verify_result = verify_text(session, t1_buffer, t1_length, sig_buffer, sig_length, &keylist);
    2.10 +    cout << "returning from verify_text() with result == " << verify_result << "\n";
    2.11      assert(verify_result == PEP_VERIFIED || verify_result == PEP_VERIFIED_AND_TRUSTED);
    2.12      assert(keylist->value);
    2.13      cout << "signed with " << keylist->value << "\n";