cipher reorganisiert
[gnupg.git] / g10 / keyid.c
index 5d5a043..02e706f 100644 (file)
@@ -1,14 +1,14 @@
 /* keyid.c - jeyid and fingerprint handling
- *     Copyright (c) 1997 by Werner Koch (dd9jn)
+ *     Copyright (C) 1998 Free Software Foundation, Inc.
  *
- * This file is part of G10.
+ * This file is part of GNUPG.
  *
- * G10 is free software; you can redistribute it and/or modify
+ * GNUPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * G10 is distributed in the hope that it will be useful,
+ * GNUPG is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -59,17 +59,15 @@ v3_elg_fingerprint_md( PKT_public_cert *pkc )
     byte *buf1, *buf2, *buf3;
     byte *p1, *p2, *p3;
     unsigned n1, n2, n3;
+    unsigned nb1, nb2, nb3;
     unsigned n;
 
+    nb1 = mpi_get_nbits(pkc->d.elg.p);
     p1 = buf1 = mpi_get_buffer( pkc->d.elg.p, &n1, NULL );
-    for( ; !*p1 && n1; p1++, n1-- )  /* skip leading null bytes */
-       ;
+    nb2 = mpi_get_nbits(pkc->d.elg.g);
     p2 = buf2 = mpi_get_buffer( pkc->d.elg.g, &n2, NULL );
-    for( ; !*p2 && n2; p2++, n2-- )  /* skip leading null bytes */
-       ;
+    nb3 = mpi_get_nbits(pkc->d.elg.y);
     p3 = buf3 = mpi_get_buffer( pkc->d.elg.y, &n3, NULL );
-    for( ; !*p3 && n3; p3++, n3-- )  /* skip leading null bytes */
-       ;
 
     /* calculate length of packet (1+4+2+1+2+n1+2+n2+2+n3) */
     n = 14 + n1 + n2 + n3;
@@ -90,9 +88,9 @@ v3_elg_fingerprint_md( PKT_public_cert *pkc )
        md_putc( md, a      );
     }
     md_putc( md, pkc->pubkey_algo );
-    md_putc( md, n1>>8); md_putc( md, n1 ); md_write( md, p1, n1 );
-    md_putc( md, n2>>8); md_putc( md, n2 ); md_write( md, p2, n2 );
-    md_putc( md, n3>>8); md_putc( md, n3 ); md_write( md, p3, n3 );
+    md_putc( md, nb1>>8); md_putc( md, nb1 ); md_write( md, p1, n1 );
+    md_putc( md, nb2>>8); md_putc( md, nb2 ); md_write( md, p2, n2 );
+    md_putc( md, nb3>>8); md_putc( md, nb3 ); md_write( md, p3, n3 );
     m_free(buf1);
     m_free(buf2);
     m_free(buf3);
@@ -101,20 +99,129 @@ v3_elg_fingerprint_md( PKT_public_cert *pkc )
     return md;
 }
 
+static MD_HANDLE
+elg_fingerprint_md( PKT_public_cert *pkc )
+{
+    MD_HANDLE md;
+    byte *buf1, *buf3, *buf4 ;
+    byte *p1, *p3, *p4;
+    unsigned n1, n3, n4;
+    unsigned nb1, nb3, nb4;
+    unsigned n;
+
+    nb1 = mpi_get_nbits(pkc->d.elg.p);
+    p1 = buf1 = mpi_get_buffer( pkc->d.elg.p, &n1, NULL );
+    nb3 = mpi_get_nbits(pkc->d.elg.g);
+    p3 = buf3 = mpi_get_buffer( pkc->d.elg.g, &n3, NULL );
+    nb4 = mpi_get_nbits(pkc->d.elg.y);
+    p4 = buf4 = mpi_get_buffer( pkc->d.elg.y, &n4, NULL );
+
+    /* calculate length of packet */
+    n = 12 + n1 + n3 +n4 ;
+    md = md_open( DIGEST_ALGO_SHA1, 0);
+
+    md_putc( md, 0x99 );     /* ctb */
+    md_putc( md, n >> 8 );   /* 2 byte length header */
+    md_putc( md, n );
+    md_putc( md, 4 );       /* version */
+    {  u32 a = pkc->timestamp;
+       md_putc( md, a >> 24 );
+       md_putc( md, a >> 16 );
+       md_putc( md, a >>  8 );
+       md_putc( md, a       );
+    }
+    md_putc( md, pkc->pubkey_algo );
+    md_putc( md, nb1>>8); md_putc( md, nb1 ); md_write( md, p1, n1 );
+    md_putc( md, nb3>>8); md_putc( md, nb3 ); md_write( md, p3, n3 );
+    md_putc( md, nb4>>8); md_putc( md, nb4 ); md_write( md, p4, n4 );
+    m_free(buf1);
+    m_free(buf3);
+    m_free(buf4);
+    md_final( md );
+
+    return md;
+}
+
+
+static MD_HANDLE
+dsa_fingerprint_md( PKT_public_cert *pkc )
+{
+    MD_HANDLE md;
+    byte *buf1, *buf2, *buf3, *buf4 ;
+    byte *p1, *p2, *p3, *p4;
+    unsigned n1, n2, n3, n4;
+    unsigned nb1, nb2, nb3, nb4;
+    unsigned n;
+
+    nb1 = mpi_get_nbits(pkc->d.dsa.p);
+    p1 = buf1 = mpi_get_buffer( pkc->d.dsa.p, &n1, NULL );
+    nb2 = mpi_get_nbits(pkc->d.dsa.q);
+    p2 = buf2 = mpi_get_buffer( pkc->d.dsa.q, &n2, NULL );
+    nb3 = mpi_get_nbits(pkc->d.dsa.g);
+    p3 = buf3 = mpi_get_buffer( pkc->d.dsa.g, &n3, NULL );
+    nb4 = mpi_get_nbits(pkc->d.dsa.y);
+    p4 = buf4 = mpi_get_buffer( pkc->d.dsa.y, &n4, NULL );
+
+    /* calculate length of packet */
+    n = 14 + n1 + n2 + n3 +n4 ;
+    md = md_open( DIGEST_ALGO_SHA1, 0);
+
+    md_putc( md, 0x99 );     /* ctb */
+    md_putc( md, n >> 8 );   /* 2 byte length header */
+    md_putc( md, n );
+    md_putc( md, 4 );       /* version */
+    {  u32 a = pkc->timestamp;
+       md_putc( md, a >> 24 );
+       md_putc( md, a >> 16 );
+       md_putc( md, a >>  8 );
+       md_putc( md, a       );
+    }
+    md_putc( md, pkc->pubkey_algo );
+    md_putc( md, nb1>>8); md_putc( md, nb1 ); md_write( md, p1, n1 );
+    md_putc( md, nb2>>8); md_putc( md, nb2 ); md_write( md, p2, n2 );
+    md_putc( md, nb3>>8); md_putc( md, nb3 ); md_write( md, p3, n3 );
+    md_putc( md, nb4>>8); md_putc( md, nb4 ); md_write( md, p4, n4 );
+    m_free(buf1);
+    m_free(buf2);
+    m_free(buf3);
+    m_free(buf4);
+    md_final( md );
+
+    return md;
+}
 
 static MD_HANDLE
-v3_elg_fingerprint_md_skc( PKT_secret_cert *skc )
+elg_fingerprint_md_skc( PKT_secret_cert *skc )
 {
     PKT_public_cert pkc;
 
     pkc.pubkey_algo = skc->pubkey_algo;
+    pkc.version     = skc->version;
     pkc.timestamp = skc->timestamp;
     pkc.valid_days = skc->valid_days;
     pkc.pubkey_algo = skc->pubkey_algo;
     pkc.d.elg.p = skc->d.elg.p;
     pkc.d.elg.g = skc->d.elg.g;
     pkc.d.elg.y = skc->d.elg.y;
-    return v3_elg_fingerprint_md( &pkc );
+    if( pkc.version < 4 )
+       return v3_elg_fingerprint_md( &pkc );
+    else
+       return elg_fingerprint_md( &pkc );
+}
+
+static MD_HANDLE
+dsa_fingerprint_md_skc( PKT_secret_cert *skc )
+{
+    PKT_public_cert pkc;
+
+    pkc.pubkey_algo = skc->pubkey_algo;
+    pkc.timestamp = skc->timestamp;
+    pkc.pubkey_algo = skc->pubkey_algo;
+    pkc.d.dsa.p = skc->d.dsa.p;
+    pkc.d.dsa.q = skc->d.dsa.q;
+    pkc.d.dsa.g = skc->d.dsa.g;
+    pkc.d.dsa.y = skc->d.dsa.y;
+    return dsa_fingerprint_md( &pkc );
 }
 
 
@@ -134,8 +241,21 @@ keyid_from_skc( PKT_secret_cert *skc, u32 *keyid )
     if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
        const byte *dp;
        MD_HANDLE md;
-       md = v3_elg_fingerprint_md_skc(skc);
-       dp = md_read( md, DIGEST_ALGO_RMD160 );
+       md = elg_fingerprint_md_skc(skc);
+       if( skc->version < 4 )
+           dp = md_read( md, DIGEST_ALGO_RMD160 );
+       else
+           dp = md_read( md, DIGEST_ALGO_SHA1 );
+       keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
+       keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
+       lowbits = keyid[1];
+       md_close(md);
+    }
+    else if( skc->pubkey_algo == PUBKEY_ALGO_DSA ) {
+       const byte *dp;
+       MD_HANDLE md;
+       md = dsa_fingerprint_md_skc(skc);
+       dp = md_read( md, DIGEST_ALGO_SHA1 );
        keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
        keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
        lowbits = keyid[1];
@@ -167,8 +287,24 @@ keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid )
     if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
        const byte *dp;
        MD_HANDLE md;
-       md = v3_elg_fingerprint_md(pkc);
-       dp = md_read( md, DIGEST_ALGO_RMD160 );
+       if( pkc->version < 4 ) {
+           md = v3_elg_fingerprint_md(pkc);
+           dp = md_read( md, DIGEST_ALGO_RMD160 );
+       }
+       else {
+           md = elg_fingerprint_md(pkc);
+           dp = md_read( md, DIGEST_ALGO_SHA1 );
+       }
+       keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
+       keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
+       lowbits = keyid[1];
+       md_close(md);
+    }
+    else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA  ) {
+       const byte *dp;
+       MD_HANDLE md;
+       md = dsa_fingerprint_md(pkc);
+       dp = md_read( md, DIGEST_ALGO_SHA1 );
        keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
        keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
        lowbits = keyid[1];
@@ -204,6 +340,9 @@ nbits_from_pkc( PKT_public_cert *pkc )
     if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
        return mpi_get_nbits( pkc->d.elg.p );
     }
+    else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) {
+       return mpi_get_nbits( pkc->d.dsa.p );
+    }
     else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
        return mpi_get_nbits( pkc->d.rsa.rsa_n );
     }
@@ -220,6 +359,9 @@ nbits_from_skc( PKT_secret_cert *skc )
     if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
        return mpi_get_nbits( skc->d.elg.p );
     }
+    else if( skc->pubkey_algo == PUBKEY_ALGO_DSA ) {
+       return mpi_get_nbits( skc->d.dsa.p );
+    }
     else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
        return mpi_get_nbits( skc->d.rsa.rsa_n );
     }
@@ -281,6 +423,7 @@ fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len )
     byte *p;
 
     pkc.pubkey_algo = skc->pubkey_algo;
+    pkc.version     = skc->version;
     if( pkc.pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
        pkc.timestamp = skc->timestamp;
        pkc.valid_days = skc->valid_days;
@@ -289,6 +432,15 @@ fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len )
        pkc.d.elg.g = skc->d.elg.g;
        pkc.d.elg.y = skc->d.elg.y;
     }
+    else if( pkc.pubkey_algo == PUBKEY_ALGO_DSA ) {
+       pkc.timestamp = skc->timestamp;
+       pkc.valid_days = skc->valid_days;
+       pkc.pubkey_algo = skc->pubkey_algo;
+       pkc.d.dsa.p = skc->d.dsa.p;
+       pkc.d.dsa.q = skc->d.dsa.q;
+       pkc.d.dsa.g = skc->d.dsa.g;
+       pkc.d.dsa.y = skc->d.dsa.y;
+    }
     else if( pkc.pubkey_algo == PUBKEY_ALGO_RSA ) {
        pkc.d.rsa.rsa_n = skc->d.rsa.rsa_n;
        pkc.d.rsa.rsa_e = skc->d.rsa.rsa_e;
@@ -311,8 +463,23 @@ fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len )
 
     if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
        MD_HANDLE md;
-       md = v3_elg_fingerprint_md(pkc);
-       dp = md_read( md, DIGEST_ALGO_RMD160 );
+       if( pkc->version < 4 ) {
+           md = v3_elg_fingerprint_md(pkc);
+           dp = md_read( md, DIGEST_ALGO_RMD160 );
+       }
+       else {
+           md = elg_fingerprint_md(pkc);
+           dp = md_read( md, DIGEST_ALGO_SHA1 );
+       }
+       array = m_alloc( 20 );
+       len = 20;
+       memcpy(array, dp, 20 );
+       md_close(md);
+    }
+    else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) {
+       MD_HANDLE md;
+       md = dsa_fingerprint_md(pkc);
+       dp = md_read( md, DIGEST_ALGO_SHA1 );
        array = m_alloc( 20 );
        len = 20;
        memcpy(array, dp, 20 );
@@ -323,13 +490,9 @@ fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len )
 
        md = md_open( DIGEST_ALGO_MD5, 0);
        p = buf = mpi_get_buffer( pkc->d.rsa.rsa_n, &n, NULL );
-       for( ; !*p && n; p++, n-- )
-           ;
        md_write( md, p, n );
        m_free(buf);
        p = buf = mpi_get_buffer( pkc->d.rsa.rsa_e, &n, NULL );
-       for( ; !*p && n; p++, n-- )
-           ;
        md_write( md, p, n );
        m_free(buf);
        md_final(md);