1 /* key.c - Key objects.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
5 This file is part of GPGME.
7 GPGME is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
12 GPGME is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
35 /* Protects all reference counters in keys. All other accesses to a
37 DEFINE_STATIC_LOCK (key_ref_lock);
40 /* Create a new key. */
42 _gpgme_key_new (gpgme_key_t *r_key)
46 key = calloc (1, sizeof *key);
48 return gpg_error_from_errno (errno);
57 _gpgme_key_add_subkey (gpgme_key_t key, gpgme_subkey_t *r_subkey)
59 gpgme_subkey_t subkey;
61 subkey = calloc (1, sizeof *subkey);
63 return gpg_error_from_errno (errno);
64 subkey->keyid = subkey->_keyid;
65 subkey->_keyid[16] = '\0';
68 key->subkeys = subkey;
69 if (key->_last_subkey)
70 key->_last_subkey->next = subkey;
71 key->_last_subkey = subkey;
79 set_user_id_part (char *tail, const char *buf, size_t len)
81 while (len && (buf[len - 1] == ' ' || buf[len - 1] == '\t'))
91 parse_user_id (char *src, char **name, char **email,
92 char **comment, char *tail)
94 const char *start = NULL;
104 /* Not legal but anyway. */
106 else if (*src == '>')
108 if (!--in_email && !*email)
111 tail = set_user_id_part (tail, start, src - start);
119 else if (*src == ')')
121 if (!--in_comment && !*comment)
124 tail = set_user_id_part (tail, start, src - start);
128 else if (*src == '<')
135 tail = set_user_id_part (tail, start, src - start);
142 else if (*src == '(')
149 tail = set_user_id_part (tail, start, src - start);
156 else if (!in_name && *src != ' ' && *src != '\t')
169 tail = set_user_id_part (tail, start, src - start);
173 /* Let unused parts point to an EOS. */
185 parse_x509_user_id (char *src, char **name, char **email,
186 char **comment, char *tail)
188 if (*src == '<' && src[strlen (src) - 1] == '>')
191 /* Let unused parts point to an EOS. */
202 /* Take a name from the --with-colon listing, remove certain escape
203 sequences sequences and put it into the list of UIDs. */
205 _gpgme_key_append_name (gpgme_key_t key, const char *src, int convert)
209 int src_len = strlen (src);
212 /* We can malloc a buffer of the same length, because the converted
213 string will never be larger. Actually we allocate it twice the
214 size, so that we are able to store the parsed stuff there too. */
215 uid = malloc (sizeof (*uid) + 2 * src_len + 3);
217 return gpg_error_from_errno (errno);
218 memset (uid, 0, sizeof *uid);
220 uid->uid = ((char *) uid) + sizeof (*uid);
223 _gpgme_decode_c_string (src, &dst, src_len + 1);
225 memcpy (dst, src, src_len + 1);
227 dst += strlen (dst) + 1;
228 if (key->protocol == GPGME_PROTOCOL_CMS)
229 parse_x509_user_id (uid->uid, &uid->name, &uid->email,
232 parse_user_id (uid->uid, &uid->name, &uid->email,
238 key->_last_uid->next = uid;
239 key->_last_uid = uid;
246 _gpgme_key_add_sig (gpgme_key_t key, char *src)
248 int src_len = src ? strlen (src) : 0;
252 assert (key); /* XXX */
254 uid = key->_last_uid;
255 assert (uid); /* XXX */
257 /* We can malloc a buffer of the same length, because the converted
258 string will never be larger. Actually we allocate it twice the
259 size, so that we are able to store the parsed stuff there too. */
260 sig = malloc (sizeof (*sig) + 2 * src_len + 3);
263 memset (sig, 0, sizeof *sig);
265 sig->keyid = sig->_keyid;
266 sig->_keyid[16] = '\0';
267 sig->uid = ((char *) sig) + sizeof (*sig);
271 char *dst = sig->uid;
272 _gpgme_decode_c_string (src, &dst, src_len + 1);
273 dst += strlen (dst) + 1;
274 if (key->protocol == GPGME_PROTOCOL_CMS)
275 parse_x509_user_id (sig->uid, &sig->name, &sig->email,
278 parse_user_id (sig->uid, &sig->name, &sig->email,
284 if (!uid->signatures)
285 uid->signatures = sig;
286 if (uid->_last_keysig)
287 uid->_last_keysig->next = sig;
288 uid->_last_keysig = sig;
294 /* Acquire a reference to KEY. */
296 gpgme_key_ref (gpgme_key_t key)
300 UNLOCK (key_ref_lock);
304 /* gpgme_key_unref releases the key object. Note, that this function
305 may not do an actual release if there are other shallow copies of
306 the objects. You have to call this function for every newly
307 created key object as well as for every gpgme_key_ref() done on the
310 gpgme_key_unref (gpgme_key_t key)
313 gpgme_subkey_t subkey;
319 assert (key->_refs > 0);
322 UNLOCK (key_ref_lock);
325 UNLOCK (key_ref_lock);
327 subkey = key->subkeys;
330 gpgme_subkey_t next = subkey->next;
333 if (subkey->card_number)
334 free (subkey->card_number);
342 gpgme_user_id_t next_uid = uid->next;
343 gpgme_key_sig_t keysig = uid->signatures;
347 gpgme_key_sig_t next_keysig = keysig->next;
348 gpgme_sig_notation_t notation = keysig->notations;
352 gpgme_sig_notation_t next_notation = notation->next;
354 _gpgme_sig_notation_free (notation);
355 notation = next_notation;
359 keysig = next_keysig;
365 if (key->issuer_serial)
366 free (key->issuer_serial);
367 if (key->issuer_name)
368 free (key->issuer_name);
371 free (key->chain_id);
377 /* Support functions. */
379 /* Create a dummy key to specify an email address. */
381 gpgme_key_from_uid (gpgme_key_t *r_key, const char *name)
387 err = _gpgme_key_new (&key);
391 /* Note: protocol doesn't matter if only email is provided. */
392 err = _gpgme_key_append_name (key, name, 0);
394 gpgme_key_unref (key);
403 /* Compatibility interfaces. */
406 gpgme_key_release (gpgme_key_t key)
408 gpgme_key_unref (key);
413 otrust_to_string (int otrust)
417 case GPGME_VALIDITY_NEVER:
420 case GPGME_VALIDITY_MARGINAL:
423 case GPGME_VALIDITY_FULL:
426 case GPGME_VALIDITY_ULTIMATE:
436 validity_to_string (int validity)
440 case GPGME_VALIDITY_UNDEFINED:
443 case GPGME_VALIDITY_NEVER:
446 case GPGME_VALIDITY_MARGINAL:
449 case GPGME_VALIDITY_FULL:
452 case GPGME_VALIDITY_ULTIMATE:
455 case GPGME_VALIDITY_UNKNOWN:
463 capabilities_to_string (gpgme_subkey_t subkey)
465 static const char *const strings[8] =
476 return strings[(!!subkey->can_encrypt << 2)
477 | (!!subkey->can_sign << 1)
478 | (!!subkey->can_certify)];
482 /* Return the value of the attribute WHAT of ITEM, which has to be
483 representable by a string. */
485 gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what,
486 const void *reserved, int idx)
488 gpgme_subkey_t subkey;
492 if (!key || reserved || idx < 0)
495 /* Select IDXth subkey. */
496 subkey = key->subkeys;
497 for (i = 0; i < idx; i++)
499 subkey = subkey->next;
504 /* Select the IDXth user ID. */
506 for (i = 0; i < idx; i++)
515 case GPGME_ATTR_KEYID:
516 return subkey ? subkey->keyid : NULL;
519 return subkey ? subkey->fpr : NULL;
521 case GPGME_ATTR_ALGO:
522 return subkey ? gpgme_pubkey_algo_name (subkey->pubkey_algo) : NULL;
524 case GPGME_ATTR_TYPE:
525 return key->protocol == GPGME_PROTOCOL_CMS ? "X.509" : "PGP";
527 case GPGME_ATTR_OTRUST:
528 return otrust_to_string (key->owner_trust);
530 case GPGME_ATTR_USERID:
531 return uid ? uid->uid : NULL;
533 case GPGME_ATTR_NAME:
534 return uid ? uid->name : NULL;
536 case GPGME_ATTR_EMAIL:
537 return uid ? uid->email : NULL;
539 case GPGME_ATTR_COMMENT:
540 return uid ? uid->comment : NULL;
542 case GPGME_ATTR_VALIDITY:
543 return uid ? validity_to_string (uid->validity) : NULL;
545 case GPGME_ATTR_KEY_CAPS:
546 return subkey ? capabilities_to_string (subkey) : NULL;
548 case GPGME_ATTR_SERIAL:
549 return key->issuer_serial;
551 case GPGME_ATTR_ISSUER:
552 return idx ? NULL : key->issuer_name;
554 case GPGME_ATTR_CHAINID:
555 return key->chain_id;
564 gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what,
565 const void *reserved, int idx)
567 gpgme_subkey_t subkey;
571 if (!key || reserved || idx < 0)
574 /* Select IDXth subkey. */
575 subkey = key->subkeys;
576 for (i = 0; i < idx; i++)
578 subkey = subkey->next;
583 /* Select the IDXth user ID. */
585 for (i = 0; i < idx; i++)
594 case GPGME_ATTR_ALGO:
595 return subkey ? (unsigned long) subkey->pubkey_algo : 0;
598 return subkey ? (unsigned long) subkey->length : 0;
600 case GPGME_ATTR_TYPE:
601 return key->protocol == GPGME_PROTOCOL_CMS ? 1 : 0;
603 case GPGME_ATTR_CREATED:
604 return (subkey && subkey->timestamp >= 0)
605 ? (unsigned long) subkey->timestamp : 0;
607 case GPGME_ATTR_EXPIRE:
608 return (subkey && subkey->expires >= 0)
609 ? (unsigned long) subkey->expires : 0;
611 case GPGME_ATTR_VALIDITY:
612 return uid ? uid->validity : 0;
614 case GPGME_ATTR_OTRUST:
615 return key->owner_trust;
617 case GPGME_ATTR_IS_SECRET:
618 return !!key->secret;
620 case GPGME_ATTR_KEY_REVOKED:
621 return subkey ? subkey->revoked : 0;
623 case GPGME_ATTR_KEY_INVALID:
624 return subkey ? subkey->invalid : 0;
626 case GPGME_ATTR_KEY_EXPIRED:
627 return subkey ? subkey->expired : 0;
629 case GPGME_ATTR_KEY_DISABLED:
630 return subkey ? subkey->disabled : 0;
632 case GPGME_ATTR_UID_REVOKED:
633 return uid ? uid->revoked : 0;
635 case GPGME_ATTR_UID_INVALID:
636 return uid ? uid->invalid : 0;
638 case GPGME_ATTR_CAN_ENCRYPT:
639 return key->can_encrypt;
641 case GPGME_ATTR_CAN_SIGN:
642 return key->can_sign;
644 case GPGME_ATTR_CAN_CERTIFY:
645 return key->can_certify;
653 static gpgme_key_sig_t
654 get_keysig (gpgme_key_t key, int uid_idx, int idx)
659 if (!key || uid_idx < 0 || idx < 0)
663 while (uid && uid_idx > 0)
671 sig = uid->signatures;
672 while (sig && idx > 0)
682 gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx,
684 const void *reserved, int idx)
686 gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx);
688 if (!certsig || reserved)
693 case GPGME_ATTR_KEYID:
694 return certsig->keyid;
696 case GPGME_ATTR_ALGO:
697 return gpgme_pubkey_algo_name (certsig->pubkey_algo);
699 case GPGME_ATTR_USERID:
702 case GPGME_ATTR_NAME:
703 return certsig->name;
705 case GPGME_ATTR_EMAIL:
706 return certsig->email;
708 case GPGME_ATTR_COMMENT:
709 return certsig->comment;
718 gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx, _gpgme_attr_t what,
719 const void *reserved, int idx)
721 gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx);
723 if (!certsig || reserved)
728 case GPGME_ATTR_ALGO:
729 return (unsigned long) certsig->pubkey_algo;
731 case GPGME_ATTR_CREATED:
732 return certsig->timestamp < 0 ? 0L : (unsigned long) certsig->timestamp;
734 case GPGME_ATTR_EXPIRE:
735 return certsig->expires < 0 ? 0L : (unsigned long) certsig->expires;
737 case GPGME_ATTR_KEY_REVOKED:
738 return certsig->revoked;
740 case GPGME_ATTR_KEY_INVALID:
741 return certsig->invalid;
743 case GPGME_ATTR_KEY_EXPIRED:
744 return certsig->expired;
746 case GPGME_ATTR_SIG_CLASS:
747 return certsig->sig_class;
749 case GPGME_ATTR_SIG_STATUS:
750 return certsig->status;