1.1 --- a/src/pEpEngine.h Thu Apr 30 19:01:58 2015 +0200
1.2 +++ b/src/pEpEngine.h Thu Apr 30 19:03:18 2015 +0200
1.3 @@ -622,7 +622,7 @@
1.4 );
1.5
1.6
1.7 -// revoke_key() - revoke an expired key
1.8 +// revoke_key() - revoke a key
1.9 //
1.10 // parameters:
1.11 // session (in) session handle
1.12 @@ -632,6 +632,8 @@
1.13 //
1.14 // caveat:
1.15 // reason text must not include empty lines
1.16 +// this function is meant for internal use only; better use
1.17 +// key_compromized() of keymanagement API
1.18
1.19 DYNAMIC_API PEP_STATUS revoke_key(
1.20 PEP_SESSION session,
2.1 --- a/src/pEp_internal.h Thu Apr 30 19:01:58 2015 +0200
2.2 +++ b/src/pEp_internal.h Thu Apr 30 19:03:18 2015 +0200
2.3 @@ -53,7 +53,7 @@
2.4
2.5 #ifdef USE_GPG
2.6 #include "pgp_gpg_internal.h"
2.7 -#elif USE_NETPGP
2.8 +#elif defined(USE_NETPGP)
2.9 #include "pgp_netpgp_internal.h"
2.10 #endif
2.11
2.12 @@ -66,7 +66,7 @@
2.13 const char *version;
2.14 #ifdef USE_GPG
2.15 gpgme_ctx_t ctx;
2.16 -#elif USE_NETPGP
2.17 +#elif defined(USE_NETPGP)
2.18 netpgp_t ctx;
2.19 #endif
2.20
3.1 --- a/src/pgp_netpgp.c Thu Apr 30 19:01:58 2015 +0200
3.2 +++ b/src/pgp_netpgp.c Thu Apr 30 19:03:18 2015 +0200
3.3 @@ -11,6 +11,7 @@
3.4 #include <netpgp/crypto.h>
3.5 #include <netpgp/netpgpsdk.h>
3.6 #include <netpgp/validate.h>
3.7 +#include <netpgp/readerwriter.h>
3.8
3.9 #include <regex.h>
3.10
3.11 @@ -52,7 +53,7 @@
3.12
3.13 // subset of gpg's personal-cipher-preferences
3.14 // here only one cipher can be selected
3.15 - netpgp_setvar(netpgp, "cipher", "AES256");
3.16 + netpgp_setvar(netpgp, "cipher", "CAST5");
3.17
3.18 if (!netpgp_init(netpgp)) {
3.19 status = PEP_INIT_NETPGP_INIT_FAILED;
3.20 @@ -98,6 +99,18 @@
3.21 return armoured;
3.22 }
3.23
3.24 +/* return key ID's hexdump as a string */
3.25 +static void id_to_str(const uint8_t *userid, char *fpr)
3.26 +{
3.27 + int i;
3.28 + static const char *hexes = "0123456789abcdef";
3.29 + for (i = 0; i < 8 ; i++) {
3.30 + fpr[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
3.31 + fpr[(i * 2) + 1] = hexes[userid[i] & 0xf];
3.32 + }
3.33 + fpr[8 * 2] = 0x0;
3.34 +}
3.35 +
3.36 // Iterate through netpgp' reported valid signatures
3.37 // fill a list of valid figerprints
3.38 // returns PEP_STATUS_OK if all sig reported valid
3.39 @@ -141,9 +154,7 @@
3.40 }
3.41 k = *_keylist;
3.42 for (n = 0; n < vresult->validc; ++n) {
3.43 - int i;
3.44 char id[MAX_ID_LENGTH + 1];
3.45 - static const char *hexes = "0123456789abcdef";
3.46 const uint8_t *userid = vresult->valid_sigs[n].signer_id;
3.47
3.48 #ifdef PEP_NETPGP_DEBUG
3.49 @@ -156,11 +167,7 @@
3.50 pgp_print_keydata(netpgp->io, netpgp->pubring, key, "valid signature ", &key->key.pubkey, 0);
3.51 #endif //PEP_NETPGP_DEBUG
3.52
3.53 - for (i = 0; i < 8 ; i++) {
3.54 - id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
3.55 - id[(i * 2) + 1] = hexes[userid[i] & 0xf];
3.56 - }
3.57 - id[8 * 2] = 0x0;
3.58 + id_to_str(userid, id);
3.59
3.60 k = stringlist_add(k, id);
3.61 if(!k){
3.62 @@ -391,7 +398,6 @@
3.63
3.64 PEP_STATUS result;
3.65 const stringlist_t *_keylist;
3.66 - int i;
3.67
3.68 assert(session);
3.69 assert(keylist);
3.70 @@ -477,7 +483,6 @@
3.71
3.72 char *_buffer = NULL;
3.73 size_t length = pgp_mem_len(cmem);
3.74 - assert(length != -1);
3.75
3.76 // Allocate transferable buffer
3.77 _buffer = malloc(length + 1);
3.78 @@ -505,19 +510,116 @@
3.79 return result;
3.80 }
3.81
3.82 +/* return the hexdump as a string */
3.83 +static unsigned
3.84 +fpr_to_str (char **str, const uint8_t *fpr, size_t length)
3.85 +{
3.86 + unsigned i;
3.87 + int n;
3.88 +
3.89 + /* 5 char per byte (hexes + space) tuple -1 space at the end + null */
3.90 + *str = malloc((length / 2) * 5 - 1 + 1);
3.91 +
3.92 + if(*str == NULL)
3.93 + return 0;
3.94 +
3.95 + for (n = 0, i = 0 ; i < length - 1; i += 2) {
3.96 + n += snprintf(&((*str)[n]), 6, "%02x%02x ", *fpr++, *fpr++);
3.97 + }
3.98 + snprintf(&((*str)[n]), 5, "%02x%02x", *fpr++, *fpr++);
3.99 +
3.100 + return 1;
3.101 +}
3.102 +
3.103 +static unsigned
3.104 +str_to_fpr (const char *str, uint8_t *fpr, size_t *length)
3.105 +{
3.106 + unsigned i,j;
3.107 +
3.108 + *length = 0;
3.109 +
3.110 + while(*str && *length < PGP_FINGERPRINT_SIZE){
3.111 + while (*str == ' ') str++;
3.112 + for (j = 0; j < 2; j++) {
3.113 + uint8_t *byte = &fpr[*length];
3.114 + for (i = 0; i < 2; i++) {
3.115 + if (i > 0)
3.116 + *byte *= 16;
3.117 + if (*str >= 'a' && *str <= 'f')
3.118 + *byte += 10 + *str - 'a';
3.119 + else if (*str >= 'A' && *str <= 'F')
3.120 + *byte += 10 + *str - 'A';
3.121 + else if (*str >= '0' && *str <= '9')
3.122 + *byte += *str - '0';
3.123 + else
3.124 + return 0;
3.125 + str++;
3.126 + }
3.127 + *length++;
3.128 + }
3.129 + }
3.130 + return 1;
3.131 +}
3.132 +
3.133 +static PEP_STATUS import_key_or_keypair(netpgp_t *netpgp, pgp_key_t *newkey){
3.134 + pgp_key_t pubkey;
3.135 + unsigned public;
3.136 + PEP_STATUS result;
3.137 +
3.138 + if ((public = (newkey->type == PGP_PTAG_CT_PUBLIC_KEY))){
3.139 + pubkey = *newkey;
3.140 + } else {
3.141 + // Duplicate key as public only
3.142 + if (!pgp_keydata_dup(&pubkey, newkey, 1 /* make_public */)){
3.143 + return PEP_OUT_OF_MEMORY;
3.144 + }
3.145 + }
3.146 +
3.147 + // Append generated key to netpgp's rings (key ownership transfered)
3.148 + if (!public && !pgp_keyring_add(netpgp->secring, newkey)){
3.149 + result = PEP_OUT_OF_MEMORY;
3.150 + goto free_pubkey;
3.151 + } else if (!pgp_keyring_add(netpgp->pubring, &pubkey)){
3.152 + result = PEP_OUT_OF_MEMORY;
3.153 + goto pop_secring;
3.154 + }
3.155 +
3.156 + // save rings
3.157 + if (netpgp_save_pubring(netpgp) &&
3.158 + (!public || netpgp_save_secring(netpgp)))
3.159 + {
3.160 + /* free nothing, everything transfered */
3.161 + return PEP_STATUS_OK;
3.162 + } else {
3.163 + /* XXX in case only pubring save succeed
3.164 + * pubring file is left as-is, but backup restore
3.165 + * could be attempted if such corner case matters */
3.166 + result = PEP_UNKNOWN_ERROR;
3.167 + }
3.168 +
3.169 +pop_pubring:
3.170 + ((pgp_keyring_t *)netpgp->pubring)->keyc--;
3.171 +pop_secring:
3.172 + ((pgp_keyring_t *)netpgp->secring)->keyc--;
3.173 +free_pubkey:
3.174 + pgp_key_free(&pubkey);
3.175 +
3.176 + return result;
3.177 +}
3.178 +
3.179 PEP_STATUS pgp_generate_keypair(
3.180 PEP_SESSION session, pEp_identity *identity
3.181 )
3.182 {
3.183 - char *parms;
3.184 - const char *template =
3.185 - "Key-Type: RSA\n"
3.186 - "Key-Length: 4096\n"
3.187 - "Name-Real: %s\n"
3.188 - "Name-Email: %s\n"
3.189 - /* "Passphrase: %s\n" */
3.190 - "Expire-Date: 1y\n";
3.191 - int result;
3.192 + netpgp_t *netpgp;
3.193 + pgp_key_t newkey;
3.194 + pgp_key_t pubkey;
3.195 +
3.196 + PEP_STATUS result;
3.197 + char newid[1024];
3.198 + const char *hashalg;
3.199 + const char *cipher;
3.200 + char *fprstr = NULL;
3.201
3.202 assert(session);
3.203 assert(identity);
3.204 @@ -525,101 +627,219 @@
3.205 assert(identity->fpr == NULL);
3.206 assert(identity->username);
3.207
3.208 - parms = calloc(1, PARMS_MAX);
3.209 - assert(parms);
3.210 - if (parms == NULL)
3.211 - return PEP_OUT_OF_MEMORY;
3.212 + if(!session || !identity ||
3.213 + !identity->address || identity->fpr || !identity->username)
3.214 + return PEP_UNKNOWN_ERROR;
3.215 +
3.216 + netpgp = &session->ctx;
3.217
3.218 - result = snprintf(parms, PARMS_MAX, template, identity->username,
3.219 - identity->address);
3.220 - assert(result < PARMS_MAX);
3.221 - if (result >= PARMS_MAX) {
3.222 - free(parms);
3.223 + if(snprintf(newid, sizeof(newid),
3.224 + "%s <%s>", identity->username, identity->address) >= sizeof(newid)){
3.225 return PEP_BUFFER_TOO_SMALL;
3.226 }
3.227 +
3.228 + hashalg = netpgp_getvar(netpgp, "hash");
3.229 + cipher = netpgp_getvar(netpgp, "cipher");
3.230 +
3.231 + bzero(&newkey, sizeof(newkey));
3.232 + bzero(&pubkey, sizeof(pubkey));
3.233 +
3.234 + // Generate the key
3.235 + if (!pgp_rsa_generate_keypair(&newkey, 4096, 65537UL, hashalg, cipher,
3.236 + (const uint8_t *) "", (const size_t) 0) ||
3.237 + !pgp_add_selfsigned_userid(&newkey, (uint8_t *)newid)) {
3.238 + result = PEP_CANNOT_CREATE_KEY;
3.239 + goto free_newkey;
3.240 + }
3.241
3.242 - /* TODO generate key */
3.243 + // TODO "Expire-Date: 1y\n";
3.244
3.245 - free(parms);
3.246 + fpr_to_str(&fprstr,
3.247 + newkey.sigfingerprint.fingerprint,
3.248 + newkey.sigfingerprint.length);
3.249 + if (fprstr == NULL) {
3.250 + result = PEP_OUT_OF_MEMORY;
3.251 + goto free_newkey;
3.252 + }
3.253 +
3.254 + result = import_key_or_keypair(netpgp, &newkey);
3.255
3.256 - return PEP_UNKNOWN_ERROR;
3.257 - return PEP_ILLEGAL_VALUE;
3.258 - return PEP_CANNOT_CREATE_KEY;
3.259 + if (result == PEP_STATUS_OK) {
3.260 + identity->fpr = fprstr;
3.261 + /* free nothing, everything transfered */
3.262 + return PEP_STATUS_OK;
3.263 + }
3.264
3.265 - identity->fpr = strdup("TODO generated key fpr");
3.266 +free_fprstr:
3.267 + free(fprstr);
3.268 +free_newkey:
3.269 + pgp_key_free(&newkey);
3.270
3.271 - return PEP_STATUS_OK;
3.272 + return result;
3.273 }
3.274
3.275 -PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr)
3.276 +PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr)
3.277 {
3.278 + netpgp_t *netpgp;
3.279 + uint8_t fpr[PGP_FINGERPRINT_SIZE];
3.280 + size_t length;
3.281 + unsigned res;
3.282 +
3.283 + PEP_STATUS result;
3.284 +
3.285 assert(session);
3.286 assert(fpr);
3.287
3.288 - /* TODO get key with given fpr */
3.289 - return PEP_KEY_NOT_FOUND;
3.290 - return PEP_ILLEGAL_VALUE;
3.291 - return PEP_KEY_HAS_AMBIG_NAME;
3.292 - return PEP_OUT_OF_MEMORY;
3.293 + if (!session || !fpr)
3.294 return PEP_UNKNOWN_ERROR;
3.295
3.296 - /* TODO delete that key */
3.297 - return PEP_UNKNOWN_ERROR;
3.298 - return PEP_KEY_NOT_FOUND;
3.299 - return PEP_KEY_HAS_AMBIG_NAME;
3.300 - return PEP_UNKNOWN_ERROR;
3.301 + netpgp = &session->ctx;
3.302 +
3.303 + if (str_to_fpr(fprstr, fpr, &length)) {
3.304 + if (!pgp_deletekeybyfpr(netpgp->io,
3.305 + (pgp_keyring_t *)netpgp->secring,
3.306 + (const uint8_t *)fpr, length)) {
3.307 + return PEP_KEY_NOT_FOUND;
3.308 + }
3.309 + }else{
3.310 + return PEP_OUT_OF_MEMORY;
3.311 + }
3.312
3.313 - return PEP_STATUS_OK;
3.314 + /* pair was found in secring delete also corresponding pubkey
3.315 + * in pubring if it exists */
3.316 + if(res) {
3.317 + pgp_deletekeybyfpr(netpgp->io,
3.318 + (pgp_keyring_t *)netpgp->pubring,
3.319 + (const uint8_t *)fpr, length);
3.320 + }
3.321 +
3.322 + // save rings (key ownership transfered)
3.323 + if (netpgp_save_pubring(netpgp) &&
3.324 + netpgp_save_secring(netpgp))
3.325 + {
3.326 + result = PEP_STATUS_OK;
3.327 + }else{
3.328 + result = PEP_UNKNOWN_ERROR;
3.329 + }
3.330 +
3.331 + return result;
3.332 }
3.333
3.334 +#define ARMOR_KEY_HEAD "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----\\s*$"
3.335 PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
3.336 {
3.337 +
3.338 + netpgp_t *netpgp;
3.339 + pgp_memory_t *mem;
3.340 + pgp_keyring_t tmpring;
3.341 +
3.342 + PEP_STATUS result;
3.343 +
3.344 assert(session);
3.345 assert(key_data);
3.346
3.347 - /* TODO import */
3.348 + if(!session || !key_data)
3.349 return PEP_UNKNOWN_ERROR;
3.350 - return PEP_ILLEGAL_VALUE;
3.351 - return PEP_UNKNOWN_ERROR;
3.352 - return PEP_STATUS_OK;
3.353 +
3.354 + netpgp = &session->ctx;
3.355 +
3.356 + mem = pgp_memory_new();
3.357 + if (mem == NULL) {
3.358 + return PEP_OUT_OF_MEMORY;
3.359 + }
3.360 + pgp_memory_add(mem, (const uint8_t*)key_data, size);
3.361 +
3.362 + if (pgp_keyring_read_from_mem(netpgp->io, &tmpring,
3.363 + _armoured(key_data, size, ARMOR_KEY_HEAD),
3.364 + mem) == 0){
3.365 + result = PEP_ILLEGAL_VALUE;
3.366 + }else if (tmpring.keyc == 0){
3.367 + result = PEP_UNKNOWN_ERROR;
3.368 + }else if (tmpring.keyc > 1){
3.369 + /* too many keys given */
3.370 + result = PEP_ILLEGAL_VALUE;
3.371 + }else{
3.372 + result = import_key_or_keypair(netpgp, &tmpring.keys[0]);
3.373 + }
3.374 +
3.375 + pgp_memory_free(mem);
3.376 +
3.377 + if (result != PEP_STATUS_OK){
3.378 + pgp_keyring_purge(&tmpring);
3.379 + }
3.380 +
3.381 + return result;
3.382 }
3.383
3.384 PEP_STATUS pgp_export_keydata(
3.385 - PEP_SESSION session, const char *fpr, char **key_data, size_t *size
3.386 + PEP_SESSION session, const char *fprstr, char **key_data, size_t *size
3.387 )
3.388 {
3.389 - size_t _size;
3.390 + netpgp_t *netpgp;
3.391 + pgp_key_t *key;
3.392 + pgp_output_t *output;
3.393 + pgp_memory_t *mem;
3.394 + uint8_t fpr[PGP_FINGERPRINT_SIZE];
3.395 + size_t fprlen;
3.396 +
3.397 + PEP_STATUS result;
3.398 char *buffer;
3.399 - int reading;
3.400 + size_t buflen;
3.401
3.402 assert(session);
3.403 assert(fpr);
3.404 assert(key_data);
3.405 assert(size);
3.406
3.407 + netpgp = &session->ctx;
3.408
3.409 - /* TODO export */
3.410 - return PEP_KEY_NOT_FOUND;
3.411 - return PEP_UNKNOWN_ERROR;
3.412 + if (!session || !fpr || !key_data || !size)
3.413 return PEP_UNKNOWN_ERROR;
3.414
3.415 - _size = /* TODO */ 0;
3.416 - assert(_size != -1);
3.417 + if (str_to_fpr(fprstr, fpr, &fprlen)) {
3.418 + unsigned from = 0;
3.419 + if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, netpgp->pubring,
3.420 + fpr, fprlen,
3.421 + &from, NULL)) == NULL) {
3.422 + return PEP_KEY_NOT_FOUND;
3.423 + }
3.424 + }else{
3.425 + return PEP_OUT_OF_MEMORY;
3.426 + }
3.427 +
3.428 + pgp_setup_memory_write(&output, &mem, 128);
3.429
3.430 - buffer = malloc(_size + 1);
3.431 - assert(buffer);
3.432 - if (buffer == NULL) {
3.433 - /* TODO clean */
3.434 + if (mem == NULL || output == NULL) {
3.435 return PEP_OUT_OF_MEMORY;
3.436 }
3.437
3.438 - // safeguard for the naive user
3.439 - buffer[_size] = 0;
3.440 + if (!pgp_write_xfer_pubkey(output, key, 1)) {
3.441 + result = PEP_UNKNOWN_ERROR;
3.442 + goto free_mem;
3.443 + }
3.444 +
3.445 + buffer = NULL;
3.446 + buflen = pgp_mem_len(mem);
3.447 +
3.448 + // Allocate transferable buffer
3.449 + buffer = malloc(buflen + 1);
3.450 + assert(buffer);
3.451 + if (buffer == NULL) {
3.452 + result = PEP_OUT_OF_MEMORY;
3.453 + goto free_mem;
3.454 + }
3.455 +
3.456 + memcpy(buffer, pgp_mem_data(mem), buflen);
3.457
3.458 *key_data = buffer;
3.459 - *size = _size;
3.460 + *size = buflen;
3.461 + (*key_data)[*size] = 0; // safeguard for naive users
3.462 + result = PEP_STATUS_OK;
3.463
3.464 - return PEP_STATUS_OK;
3.465 +free_mem :
3.466 + pgp_teardown_memory_write(output, mem);
3.467 +
3.468 + return result;
3.469 }
3.470
3.471 // "keyserver"
3.472 @@ -774,7 +994,11 @@
3.473 return PEP_STATUS_OK;
3.474 }
3.475
3.476 -PEP_STATUS pgp_revoke_key(PEP_SESSION session, const char *fpr)
3.477 +PEP_STATUS pgp_revoke_key(
3.478 + PEP_SESSION session,
3.479 + const char *fpr,
3.480 + const char *reason
3.481 + )
3.482 {
3.483 PEP_STATUS status = PEP_STATUS_OK;
3.484
3.485 @@ -786,3 +1010,23 @@
3.486 return PEP_STATUS_OK;
3.487 }
3.488
3.489 +PEP_STATUS pgp_key_expired(
3.490 + PEP_SESSION session,
3.491 + const char *fpr,
3.492 + bool *expired
3.493 + )
3.494 +{
3.495 + PEP_STATUS status = PEP_STATUS_OK;
3.496 +
3.497 + assert(session);
3.498 + assert(fpr);
3.499 + assert(expired);
3.500 +
3.501 + *expired = false;
3.502 +
3.503 + if (status != PEP_STATUS_OK)
3.504 + return status;
3.505 +
3.506 + return PEP_STATUS_OK;
3.507 +}
3.508 +
4.1 --- a/src/pgp_netpgp.h Thu Apr 30 19:01:58 2015 +0200
4.2 +++ b/src/pgp_netpgp.h Thu Apr 30 19:03:18 2015 +0200
4.3 @@ -44,7 +44,6 @@
4.4 size_t size);
4.5
4.6 PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern);
4.7 -
4.8 PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern);
4.9
4.10 PEP_STATUS pgp_renew_key(
4.11 @@ -53,4 +52,15 @@
4.12 const timestamp *ts
4.13 );
4.14
4.15 -PEP_STATUS pgp_revoke_key(PEP_SESSION session, const char *fpr);
4.16 +PEP_STATUS pgp_revoke_key(
4.17 + PEP_SESSION session,
4.18 + const char *fpr,
4.19 + const char *reason
4.20 + );
4.21 +
4.22 +PEP_STATUS pgp_key_expired(
4.23 + PEP_SESSION session,
4.24 + const char *fpr,
4.25 + bool *expired
4.26 + );
4.27 +
5.1 --- a/src/platform_unix.h Thu Apr 30 19:01:58 2015 +0200
5.2 +++ b/src/platform_unix.h Thu Apr 30 19:03:18 2015 +0200
5.3 @@ -4,6 +4,10 @@
5.4 #include <strings.h>
5.5 #include <sys/select.h>
5.6
5.7 +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
5.8 +#define USE_NETPGP
5.9 +#endif
5.10 +
5.11 #ifdef __cplusplus
5.12 extern "C" {
5.13 #endif