diff options
author | Werner Koch <wk@gnupg.org> | 2008-06-26 21:09:07 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2008-06-26 21:09:07 +0200 |
commit | a6a9181818d86219da202137c1697b826a3ea151 (patch) | |
tree | eeaf866d273a9308bf19091b06cd248333cc058a /sm | |
parent | g10/ (diff) | |
download | gnupg2-a6a9181818d86219da202137c1697b826a3ea151.tar.xz gnupg2-a6a9181818d86219da202137c1697b826a3ea151.zip |
Start support of TCOS 3 cards.
Support restriction attribute.
Fix utf-8 printing problems.
Use AES by default.
Diffstat (limited to 'sm')
-rw-r--r-- | sm/ChangeLog | 13 | ||||
-rw-r--r-- | sm/gpgsm.c | 2 | ||||
-rw-r--r-- | sm/gpgsm.h | 2 | ||||
-rw-r--r-- | sm/keylist.c | 122 | ||||
-rw-r--r-- | sm/qualified.c | 1 | ||||
-rw-r--r-- | sm/sign.c | 113 |
6 files changed, 197 insertions, 56 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog index 20ab48302..a6a584b38 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,16 @@ +2008-06-25 Werner Koch <wk@g10code.com> + + * sign.c (gpgsm_sign): Revamp the hash algorithm selection. + * gpgsm.h (struct certlist_s): Add field HASH_ALGO and HASH_ALGO_OID. + + * qualified.c (gpgsm_qualified_consent): Fix double free. + + * gpgsm.c (main): Change default cipher algo to AES. + + * keylist.c (print_utf8_extn_raw, print_utf8_extn): New. + (list_cert_raw, list_cert_std): Print the TeleSec restriction + extension. + 2008-06-23 Werner Koch <wk@g10code.com> * encrypt.c (encode_session_key): Replace xmalloc by xtrymalloc. diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 50ffb84d2..dfbe82675 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -987,7 +987,7 @@ main ( int argc, char **argv) create_dotlock (NULL); /* register locking cleanup */ i18n_init(); - opt.def_cipher_algoid = "3DES"; /*des-EDE3-CBC*/ + opt.def_cipher_algoid = "AES"; /*des-EDE3-CBC*/ opt.homedir = default_homedir (); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index acc53b574..2cd177504 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -207,6 +207,8 @@ struct certlist_s ksba_cert_t cert; int is_encrypt_to; /* True if the certificate has been set through the --encrypto-to option. */ + int hash_algo; /* Used to track the hash algorithm to use. */ + const char *hash_algo_oid; /* And the corresponding OID. */ }; typedef struct certlist_s *certlist_t; diff --git a/sm/keylist.c b/sm/keylist.c index 870ddf46d..6dcdc8d4d 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -1,6 +1,6 @@ /* keylist.c - Print certificates in various formats. * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2004, 2005 Free Software Foundation, Inc. + * 2004, 2005, 2008 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -35,6 +35,7 @@ #include "keydb.h" #include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */ #include "i18n.h" +#include "tlv.h" struct list_external_parm_s { @@ -77,12 +78,18 @@ struct }; +/* Do not print this extension in the list of extensions. This is set + for oids which are already available via ksba fucntions. */ +#define OID_FLAG_SKIP 1 +/* The extension is a simple UTF8String and should be printed. */ +#define OID_FLAG_UTF8 2 + /* A table mapping OIDs to a descriptive string. */ static struct { char *oid; char *name; - unsigned int flag; + unsigned int flag; /* A flag as described above. */ } oidtranstbl[] = { /* Algorithms. */ @@ -115,6 +122,10 @@ static struct { "0.2.262.1.10.12.4", "telesecCRLFilteredExt" }, { "0.2.262.1.10.12.5", "telesecCRLFilterExt"}, { "0.2.262.1.10.12.6", "telesecNamingAuthorityExt" }, +#define OIDSTR_restriction \ + "1.3.36.8.3.8" + { OIDSTR_restriction, "restriction", OID_FLAG_UTF8 }, + /* PKIX private extensions. */ { "1.3.6.1.5.5.7.1.1", "authorityInfoAccess" }, @@ -135,12 +146,12 @@ static struct { "1.3.6.1.5.5.7.48.5", "caRepository" }, /* X.509 id-ce */ - { "2.5.29.14", "subjectKeyIdentifier", 1}, - { "2.5.29.15", "keyUsage", 1 }, + { "2.5.29.14", "subjectKeyIdentifier", OID_FLAG_SKIP}, + { "2.5.29.15", "keyUsage", OID_FLAG_SKIP}, { "2.5.29.16", "privateKeyUsagePeriod" }, - { "2.5.29.17", "subjectAltName", 1 }, - { "2.5.29.18", "issuerAltName", 1 }, - { "2.5.29.19", "basicConstraints", 1}, + { "2.5.29.17", "subjectAltName", OID_FLAG_SKIP}, + { "2.5.29.18", "issuerAltName", OID_FLAG_SKIP}, + { "2.5.29.19", "basicConstraints", OID_FLAG_SKIP}, { "2.5.29.20", "cRLNumber" }, { "2.5.29.21", "cRLReason" }, { "2.5.29.22", "expirationDate" }, @@ -150,13 +161,13 @@ static struct { "2.5.29.28", "issuingDistributionPoint" }, { "2.5.29.29", "certificateIssuer" }, { "2.5.29.30", "nameConstraints" }, - { "2.5.29.31", "cRLDistributionPoints", 1 }, - { "2.5.29.32", "certificatePolicies", 1 }, + { "2.5.29.31", "cRLDistributionPoints", OID_FLAG_SKIP}, + { "2.5.29.32", "certificatePolicies", OID_FLAG_SKIP}, { "2.5.29.32.0", "anyPolicy" }, { "2.5.29.33", "policyMappings" }, - { "2.5.29.35", "authorityKeyIdentifier", 1 }, + { "2.5.29.35", "authorityKeyIdentifier", OID_FLAG_SKIP}, { "2.5.29.36", "policyConstraints" }, - { "2.5.29.37", "extKeyUsage", 1 }, + { "2.5.29.37", "extKeyUsage", OID_FLAG_SKIP}, { "2.5.29.46", "freshestCRL" }, { "2.5.29.54", "inhibitAnyPolicy" }, @@ -561,6 +572,59 @@ print_names_raw (estream_t fp, int indent, ksba_name_t name) } +static void +print_utf8_extn_raw (estream_t fp, int indent, + const unsigned char *der, size_t derlen) +{ + gpg_error_t err; + int class, tag, constructed, ndef; + size_t objlen, hdrlen; + + if (indent < 0) + indent = - indent; + + err = parse_ber_header (&der, &derlen, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > derlen || tag != TAG_UTF8_STRING)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + { + es_fprintf (fp, "%*s[%s]\n", indent, "", gpg_strerror (err)); + return; + } + es_fprintf (fp, "%*s(%.*s)\n", indent, "", objlen, der); +} + + +static void +print_utf8_extn (estream_t fp, int indent, + const unsigned char *der, size_t derlen) +{ + gpg_error_t err; + int class, tag, constructed, ndef; + size_t objlen, hdrlen; + int indent_all; + + if ((indent_all = (indent < 0))) + indent = - indent; + + err = parse_ber_header (&der, &derlen, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > derlen || tag != TAG_UTF8_STRING)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + { + es_fprintf (fp, "%*s[Error - %s]\n", + indent_all? indent:0, "", gpg_strerror (err)); + return; + } + es_fprintf (fp, "%*s\"", indent_all? indent:0, ""); + /* Fixme: we should implement word wrapping */ + es_write_sanitized (fp, der, objlen, "\"", NULL); + es_fputs ("\"\n", fp); +} + + /* List one certificate in raw mode useful to have a closer look at the certificate. This one does no beautification and only minimal output sanitation. It is mainly useful for debugging. */ @@ -581,6 +645,7 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, const char *oid, *s; ksba_name_t name, name2; unsigned int reason; + const unsigned char *cert_der = NULL; es_fprintf (fp, " ID: 0x%08lX\n", gpgsm_get_short_fingerprint (cert)); @@ -892,11 +957,19 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, unsigned int flag; s = get_oid_desc (oid, &flag); + if ((flag & OID_FLAG_SKIP)) + continue; - if (!(flag & 1)) - es_fprintf (fp, " %s: %s%s%s%s [%d octets]\n", - i? "critExtn":" extn", - oid, s?" (":"", s?s:"", s?")":"", (int)len); + es_fprintf (fp, " %s: %s%s%s%s [%d octets]\n", + i? "critExtn":" extn", + oid, s?" (":"", s?s:"", s?")":"", (int)len); + if ((flag & OID_FLAG_UTF8)) + { + if (!cert_der) + cert_der = ksba_cert_get_image (cert, NULL); + assert (cert_der); + print_utf8_extn_raw (fp, -15, cert_der+off, len); + } } @@ -938,6 +1011,10 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret, int is_ca, chainlen; unsigned int kusage; char *string, *p, *pend; + size_t off, len; + const char *oid; + const unsigned char *cert_der = NULL; + es_fprintf (fp, " ID: 0x%08lX\n", gpgsm_get_short_fingerprint (cert)); @@ -1053,6 +1130,21 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret, es_putc ('\n', fp); } + /* Print restrictions. */ + for (idx=0; !(err=ksba_cert_get_extension (cert, idx, + &oid, NULL, &off, &len));idx++) + { + if (!strcmp (oid, OIDSTR_restriction) ) + { + if (!cert_der) + cert_der = ksba_cert_get_image (cert, NULL); + assert (cert_der); + es_fputs (" restriction: ", fp); + print_utf8_extn (fp, 15, cert_der+off, len); + } + } + + /* Print policies. */ err = ksba_cert_get_cert_policies (cert, &string); if (gpg_err_code (err) != GPG_ERR_NO_DATA) { diff --git a/sm/qualified.c b/sm/qualified.c index 507c1517f..d90272804 100644 --- a/sm/qualified.c +++ b/sm/qualified.c @@ -215,7 +215,6 @@ gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert) err = 0; i18n_switchback (orig_codeset); - xfree (orig_codeset); xfree (subject); if (err) @@ -1,5 +1,5 @@ /* sign.c - Sign a message - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2008 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -396,6 +396,44 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, release_signerlist = 1; } + /* Figure out the hash algorithm to use. We do not want to use the + one for the certificate but if possible an OID for the plain + algorithm. */ + for (i=0, cl=signerlist; cl; cl = cl->next, i++) + { + const char *oid = ksba_cert_get_digest_algo (cl->cert); + + cl->hash_algo = oid ? gcry_md_map_name (oid) : 0; + switch (cl->hash_algo) + { + case GCRY_MD_SHA1: oid = "1.3.14.3.2.26"; break; + case GCRY_MD_RMD160: oid = "1.3.36.3.2.1"; break; + case GCRY_MD_SHA224: oid = "2.16.840.1.101.3.4.2.4"; break; + case GCRY_MD_SHA256: oid = "2.16.840.1.101.3.4.2.1"; break; + case GCRY_MD_SHA384: oid = "2.16.840.1.101.3.4.2.2"; break; + case GCRY_MD_SHA512: oid = "2.16.840.1.101.3.4.2.3"; break; +/* case GCRY_MD_WHIRLPOOL: oid = "No OID yet"; break; */ + + case GCRY_MD_MD5: /* We don't want to use MD5. */ + case 0: /* No algorithm found in cert. */ + default: /* Other algorithms. */ + log_info (_("hash algorithm %d (%s) for signer %d not supported;" + " using %s\n"), + cl->hash_algo, oid? oid: "?", i, + gcry_md_algo_name (GCRY_MD_SHA1)); + cl->hash_algo = GCRY_MD_SHA1; + oid = "1.3.14.3.2.26"; + break; + } + cl->hash_algo_oid = oid; + } + if (opt.verbose) + { + for (i=0, cl=signerlist; cl; cl = cl->next, i++) + log_info (_("hash algorithm used for signer %d: %s (%s)\n"), + i, gcry_md_algo_name (cl->hash_algo), cl->hash_algo_oid); + } + /* Gather certificates of signers and store them in the CMS object. */ for (cl=signerlist; cl; cl = cl->next) @@ -419,7 +457,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, goto leave; } /* Set the hash algorithm we are going to use */ - err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/); + err = ksba_cms_add_digest_algo (cms, cl->hash_algo_oid); if (err) { log_debug ("ksba_cms_add_digest_algo failed: %s\n", @@ -458,7 +496,8 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, } } - /* Prepare hashing (actually we are figuring out what we have set above)*/ + /* Prepare hashing (actually we are figuring out what we have set + above). */ rc = gcry_md_open (&data_md, 0, 0); if (rc) { @@ -474,10 +513,6 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, if (!algo) { log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?"); - if (algoid - && ( !strcmp (algoid, "1.2.840.113549.1.1.2") - ||!strcmp (algoid, "1.2.840.113549.2.2"))) - log_info (_("(this is the MD2 algorithm)\n")); rc = gpg_error (GPG_ERR_BUG); goto leave; } @@ -485,26 +520,23 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, } if (detached) - { /* we hash the data right now so that we can store the message + { /* We hash the data right now so that we can store the message digest. ksba_cms_build() takes this as an flag that detached data is expected. */ unsigned char *digest; size_t digest_len; - /* Fixme do this for all signers and get the algo to use from - the signer's certificate - does not make much sense, but we - should do this consistent as we have already done it above. */ - algo = GCRY_MD_SHA1; + hash_data (data_fd, data_md); - digest = gcry_md_read (data_md, algo); - digest_len = gcry_md_get_algo_dlen (algo); - if ( !digest || !digest_len) - { - log_error ("problem getting the hash of the data\n"); - rc = gpg_error (GPG_ERR_BUG); - goto leave; - } for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) { + digest = gcry_md_read (data_md, cl->hash_algo); + digest_len = gcry_md_get_algo_dlen (cl->hash_algo); + if ( !digest || !digest_len ) + { + log_error ("problem getting the hash of the data\n"); + rc = gpg_error (GPG_ERR_BUG); + goto leave; + } err = ksba_cms_set_message_digest (cms, signer, digest, digest_len); if (err) { @@ -559,30 +591,26 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, } if (stopreason == KSBA_SR_BEGIN_DATA) - { /* hash the data and store the message digest */ + { + /* Hash the data and store the message digest. */ unsigned char *digest; size_t digest_len; assert (!detached); - /* Fixme: get the algo to use from the signer's certificate - - does not make much sense, but we should do this - consistent as we have already done it above. Code is - mostly duplicated above. */ - algo = GCRY_MD_SHA1; rc = hash_and_copy_data (data_fd, data_md, writer); if (rc) goto leave; - digest = gcry_md_read (data_md, algo); - digest_len = gcry_md_get_algo_dlen (algo); - if ( !digest || !digest_len) - { - log_error ("problem getting the hash of the data\n"); - rc = gpg_error (GPG_ERR_BUG); - goto leave; - } for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) { + digest = gcry_md_read (data_md, cl->hash_algo); + digest_len = gcry_md_get_algo_dlen (cl->hash_algo); + if ( !digest || !digest_len ) + { + log_error ("problem getting the hash of the data\n"); + rc = gpg_error (GPG_ERR_BUG); + goto leave; + } err = ksba_cms_set_message_digest (cms, signer, digest, digest_len); if (err) @@ -595,11 +623,11 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, } } else if (stopreason == KSBA_SR_NEED_SIG) - { /* calculate the signature for all signers */ + { + /* Compute the signature for all signers. */ gcry_md_hd_t md; - algo = GCRY_MD_SHA1; - rc = gcry_md_open (&md, algo, 0); + rc = gcry_md_open (&md, 0, 0); if (rc) { log_error ("md_open failed: %s\n", gpg_strerror (rc)); @@ -615,6 +643,13 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, if (signer) gcry_md_reset (md); + { + certlist_t cl_tmp; + + for (cl_tmp=signerlist; cl_tmp; cl_tmp = cl_tmp->next) + gcry_md_enable (md, cl_tmp->hash_algo); + } + rc = ksba_cms_hash_signed_attrs (cms, signer); if (rc) { @@ -625,7 +660,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, } rc = gpgsm_create_cms_signature (ctrl, cl->cert, - md, algo, &sigval); + md, cl->hash_algo, &sigval); if (rc) { gcry_md_close (md); @@ -656,7 +691,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, rc = asprintf (&buf, "%c %d %d 00 %s %s", detached? 'D':'S', pkalgo, - algo, + cl->hash_algo, signed_at, fpr); } |