diff -c pgp_263i/crypto.c pgp_sha1/crypto.c *** pgp_263i/crypto.c Wed Jun 19 22:14:21 1996 --- pgp_sha1/crypto.c Wed Jun 19 22:45:58 1996 *************** *** 74,80 **** --- 74,86 ---- /* This variable stores the md5 hash of the current file, if it is available. It is used in make_random_ideakey. */ + #ifdef SHA1 + #include "sha1.h" + static boolean local_sha1_flag = FALSE; + static unsigned char md5buf[20]; + #else static unsigned char md5buf[16]; + #endif /* This flag is set if the buffer above has been filled. */ static char already_have_md5 = 0; *************** *** 734,739 **** --- 740,752 ---- complete message digest packet in a single RSA block. */ blocksize = countbytes(n)-1; /* size of a plaintext block */ + #ifdef SHA1 + if ((blocksize < 32) && local_sha1_flag) { + fprintf(pgpout, + "\n\007Error: RSA key length must be at least 264 bits.\n"); + return -1; + } else + #endif if (blocksize < 31) { fprintf(pgpout, "\n\007Error: RSA key length must be at least 256 bits.\n"); *************** *** 751,758 **** --- 764,781 ---- convert_byteorder(timestamp,4); /* convert to external form */ /* Finish off message digest calculation with this information */ + #ifdef SHA1 + if (local_sha1_flag) { + SHA1_addbuffer ((struct SHA1Context *)MD, &class, 1, 0); + SHA1_addbuffer ((struct SHA1Context *)MD, timestamp, 4, md5buf); + } else { + MD_addbuffer (MD, &class, 1, 0); + MD_addbuffer (MD, timestamp, 4, md5buf); + } + #else MD_addbuffer (MD, &class, 1, 0); MD_addbuffer (MD, timestamp, 4, md5buf); + #endif /* We wrote the digest to a static variable because we want to keep it around for random number generation later. Also make a note of that fact. */ already_have_md5 = 1; *************** *** 764,771 **** --- 787,803 ---- } /* do RSA signature calculation: */ + #ifdef SHA1 + if (local_sha1_flag) + i = rsa_private_encrypt((unitptr)outbuf, md5buf, 20, + e, d, p, q, u, n); + else + i = rsa_private_encrypt((unitptr)outbuf, md5buf, 16, + e, d, p, q, u, n); + #else i = rsa_private_encrypt((unitptr)outbuf, md5buf, sizeof(md5buf), e, d, p, q, u, n); + #endif if (i < 0) { if (i == -4) { fprintf(pgpout, *************** *** 823,828 **** --- 855,865 ---- certificate[certificate_length++] = keyID[i]; certificate[certificate_length++] = RSA_ALGORITHM_BYTE; + #ifdef SHA1 + if (local_sha1_flag) + certificate[certificate_length++] = SHA1_ALGORITHM_BYTE; + else + #endif certificate[certificate_length++] = MD5_ALGORITHM_BYTE; /* Now append first two bytes of message digest */ *************** *** 893,898 **** --- 930,938 ---- char keyfile[MAX_PATH]; int status; struct MD5Context MD; + #ifdef SHA1 + struct SHA1Context SH; + #endif byte keyID[KEYFRAGSIZE]; unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION]; unit d[MAX_UNIT_PRECISION]; *************** *** 907,912 **** --- 947,961 ---- "signfile: infile = '%s', outfile = '%s', mode = '%c', literalfile = '%s'\n", infile,outfile,EXT_C(lit_mode),literalfile); + #ifdef SHA1 + local_sha1_flag = FALSE; + if (mdalg_flag == SHA1_ALGORITHM_BYTE) + { + if (SHA1file(&SH, infile) < 0) + return -1; /* problem with input file. error return */ + } + else + #endif if (MDfile(&MD, infile) < 0) return -1; /* problem with input file. error return */ *************** *** 930,938 **** --- 979,1000 ---- if (lit_mode==MODE_TEXT) signature_class = SM_SIGNATURE_BYTE; else signature_class = SB_SIGNATURE_BYTE; + #ifdef SHA1 + if (mdalg_flag == SHA1_ALGORITHM_BYTE) + { + local_sha1_flag = TRUE; + certificate_length = make_signature_certificate(certificate, + (struct MD5Context *)&SH, + signature_class, e, d, p, q, u, n); + } + else + #endif certificate_length = make_signature_certificate(certificate, &MD, signature_class, e, d, p, q, u, n); + #ifdef SHA1 + local_sha1_flag = FALSE; + #endif if (certificate_length < 0) return -1; /* error return from make_signature_certificate() */ *************** *** 1088,1093 **** --- 1150,1158 ---- } set_precision(prec); + #ifdef SHA1 + local_sha1_flag = FALSE; + #endif certificate_length = make_signature_certificate(certificate, &MD, KC_SIGNATURE_BYTE, e, d, p, q, u, n); if (certificate_length < 0) { *************** *** 1246,1251 **** --- 1311,1319 ---- error return. */ } + #ifdef SHA1 + local_sha1_flag = FALSE; + #endif certificate_length = make_signature_certificate(certificate, &MD, K0_SIGNATURE_BYTE, e, d, p, q, *************** *** 1382,1388 **** --- 1450,1461 ---- word32 dummystamp; byte userid[256]; struct MD5Context MD; + #ifdef SHA1 + struct SHA1Context SH; + byte digest[20]; + #else byte digest[16]; + #endif boolean separate_signature; boolean fixedLiteral = FALSE; /* Whether it's a fixed literal2 packet */ *************** *** 1409,1414 **** --- 1482,1490 ---- extern Boolean bad_separate_signature; #endif int outbufoffset; + #ifdef SHA1 + local_sha1_flag = FALSE; + #endif fill0( keyID, KEYFRAGSIZE ); *************** *** 1486,1491 **** --- 1562,1572 ---- goto err1; algorithm = *certificate++; + #ifdef SHA1 + if (algorithm == SHA1_ALGORITHM_BYTE) + local_sha1_flag = TRUE; + else + #endif if (version_error(algorithm, MD5_ALGORITHM_BYTE)) goto err1; *************** *** 1686,1692 **** --- 1767,1778 ---- /*==================================================================*/ /* Look at nested stuff within RSA block... */ + #ifdef SHA1 + if (count == -7 || (count > 0 && local_sha1_flag && count != 20) + || (count > 0 && !local_sha1_flag && count != 16)) + #else if (count == -7 || (count > 0 && count != sizeof(digest))) + #endif { fputs(LANG("\007\nUnrecognized message digest algorithm.\n\ This may require a newer version of PGP.\n\ *************** *** 1714,1720 **** --- 1800,1812 ---- } /* Distinguish PKCS-compatible from pre-3.3 which has an extra byte */ + #ifdef SHA1 + outbufoffset = (count==16) ? 0 : 1; + if (local_sha1_flag) + outbufoffset = 0; + #else outbufoffset = (count==sizeof(digest)) ? 0 : 1; + #endif if (outbuf[outbufoffset] != mdlow2[0] || outbuf[outbufoffset+1] != mdlow2[1]) *************** *** 1729,1737 **** --- 1821,1839 ---- /* Reposition file to where that plaintext begins... */ fseek(f,start_text,SEEK_SET); /* reposition file from last ftell */ + #ifdef SHA1 + if (local_sha1_flag) + SHA1file0_len(&SH,f,text_len); + else + #endif MDfile0_len(&MD,f,text_len); /* compute a message digest from rest of file */ + #ifdef SHA1 + if (local_sha1_flag) + SHA1_addbuffer (&SH, mdextras, mdlensave, digest); + else + #endif MD_addbuffer (&MD, mdextras, mdlensave, digest); /* Finish message digest */ *************** *** 1741,1747 **** --- 1843,1853 ---- /* now compare computed MD with claimed MD */ /* Assume MSB external byte ordering */ + #ifdef SHA1 + if (!equal_buffers(digest, outbuf+outbufoffset, local_sha1_flag ? 20 : 16)) { + #else if (!equal_buffers(digest, outbuf+outbufoffset, 16)) { + #endif /* IF the signature is bad, AND this machine does not use MSDOS-stype canonical text as its native text format, AND this is a detached signature certificate, AND this file *************** *** 1766,1772 **** --- 1872,1889 ---- != NULL ) { /* Now check the signature */ + #ifdef SHA1 + if (local_sha1_flag) + SHA1file0_len(&SH, tempFile, -1L ); + else + #endif MDfile0_len(&MD, tempFile, -1L ); + #ifdef SHA1 + if (local_sha1_flag) + SHA1_addbuffer(&SH, mdextras, mdlensave, + digest); + else + #endif MD_addbuffer(&MD, mdextras, mdlensave, digest); *************** *** 1777,1788 **** --- 1894,1913 ---- /* Check if the signature is OK this time round */ /* Assume MSB external byte ordering */ + #ifdef SHA1 + if(equal_buffers(digest, outbuf+outbufoffset, + local_sha1_flag ? 20 : 16)) + #else if(equal_buffers(digest, outbuf+outbufoffset, 16)) + #endif goto goodsig; } } + #ifdef SHA1 + local_sha1_flag = FALSE; + #endif if (checksig_pass == 1) { /* Bad signature - try one more pass with other charset */ checksig_pass++; return -1; *************** *** 1819,1824 **** --- 1944,1955 ---- fprintf(pgpout, LANG("Signature made %s using %d-bit key, key ID %s\n"), ctdate((word32 *)timestamp), countbits(n), key2IDstring(n)); + #ifdef SHA1 + if (local_sha1_flag) + fprintf(pgpout, + LANG("Signature made using the SHA1 message digest algorithm.\n")); + local_sha1_flag = FALSE; + #endif #ifdef MACTC5 AddResult((char *)userid); #endif diff -c pgp_263i/pgp.c pgp_sha1/pgp.c *** pgp_263i/pgp.c Wed Jun 19 22:14:24 1996 --- pgp_sha1/pgp.c Wed Jun 19 22:22:17 1996 *************** *** 161,166 **** --- 161,170 ---- void Exit(int x); #endif + #ifdef SHA1 + #include "sha1.h" + #endif + #ifdef M_XENIX char *strstr(); long time(); *************** *** 894,899 **** --- 898,906 ---- case 'w': wipeflag = TRUE; break; + case 'x': + mdalg_flag = SHA1_ALGORITHM_BYTE; + break; case 'z': break; /* '+' special option: does not require - */ diff -c pgp_263i/rsaglue1.c pgp_sha1/rsaglue1.c *** pgp_263i/rsaglue1.c Wed Jun 19 22:14:35 1996 --- pgp_sha1/rsaglue1.c Thu Jun 20 07:27:44 1996 *************** *** 53,58 **** --- 53,99 ---- static byte asn_array[] = { /* PKCS 01 block type 01 data */ 0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, 0x02,0x05,0x05,0x00,0x04,0x10 }; + #ifdef SHA1 + static byte sha1_asn_array[] = { + 0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a, + 0x05,0x00,0x04,0x14 }; + /* + Taken from Internet Draft draft-ietf-cat-spkmgss-06, + "The Simple Public-Key GSS-API Mechanism (SPKM)", by + C. Adams, Bell-Northern Research, Jan. 19, 1996. See + also "Working Implementation Agreements for Open Systems + Interconnection Protocols: Part 12 - OS Security, Output + from the December 1994 Open Systems Environment + Implementors' Workshop (OIW)" + + SHA1 OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) oiw(14) secsig(3) + algorithm(2) 26 + } + + ASN.1 encoding: + 0x30, / * Universal, Constructed, Sequence * / + 0x21, / * Length 33 (bytes following) * / + 0x30, / * Universal, Constructed, Sequence * / + 0x09, / * Length 9 * / + 0x06, / * Universal, Primitive, object-identifier * / + 0x05, / * Length 5 * / + 43, / * 43 = ISO(1)*40 + 3 * / + 14, + 3, + 2, + 26, + 0x05, / * Universal, Primitive, NULL * / + 0x00, / * Length 0 * / + 0x04, / * Universal, Primitive, Octet string * / + 0x14 / * Length 20 * / + / * 20 SHA.1 digest bytes go here * / + + Cf. "A Layman's Guide to a Subset of ASN.1, BER, and DER -- + An RSA Laboratories Technical Note" by Burton S. Kaliski Jr. + Revised November 1, 1993 + */ + #endif /* SHA1 */ /* This many bytes from the end, there's a zero byte */ #define ASN_ZERO_END 3 *************** *** 144,149 **** --- 185,195 ---- *p++ = 0; i = blocksize - 2 - bytes; /* Padding needed */ + #ifdef SHA1 + if (bytes == 20) + i -= sizeof(sha1_asn_array); /* Space for type encoding */ + else + #endif i -= sizeof(asn_array); /* Space for type encoding */ if (i < 0) { i = -4; /* Error code */ *************** *** 153,160 **** --- 199,215 ---- memset(p, ~0, i); /* All 1's padding */ p += i; *p++ = 0; /* Zero framing byte */ + #ifdef SHA1 + if (bytes == 20) { + memcpy(p, sha1_asn_array, sizeof(sha1_asn_array)); /* ASN data */ + p += sizeof(sha1_asn_array); + } else { + #endif memcpy(p, asn_array, sizeof(asn_array)); /* ASN data */ p += sizeof(asn_array); + #ifdef SHA1 + } + #endif memcpy(p, inbuf, bytes); /* User data */ mp_convert_order((byte *)temp); *************** *** 241,250 **** --- 296,315 ---- if (front[-1]) /* First non-FF byte should be 0 */ goto ErrorReturn; /* Then comes the ASN header */ + #ifdef SHA1 + if (memcmp(front, asn_array, sizeof(asn_array))) { + if (memcmp(front, sha1_asn_array, sizeof(sha1_asn_array))) { + mp_burn(temp); + return -7; + } + front += sizeof(sha1_asn_array); + } else + #else if (memcmp(front, asn_array, sizeof(asn_array))) { mp_burn(temp); return -7; } + #endif front += sizeof(asn_array); } diff -c pgp_263i/rsaglue2.c pgp_sha1/rsaglue2.c *** pgp_263i/rsaglue2.c Wed Jun 19 22:14:21 1996 --- pgp_sha1/rsaglue2.c Fri Jun 21 17:41:47 1996 *************** *** 175,180 **** --- 175,221 ---- static byte asn_array[] = { /* PKCS 01 block type 01 data */ 0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, 0x02,0x05,0x05,0x00,0x04,0x10 }; + #ifdef SHA1 + static byte sha1_asn_array[] = { + 0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a, + 0x05,0x00,0x04,0x14 }; + /* + Taken from Internet Draft draft-ietf-cat-spkmgss-06, + "The Simple Public-Key GSS-API Mechanism (SPKM)", by + C. Adams, Bell-Northern Research, Jan. 19, 1996. See + also "Working Implementation Agreements for Open Systems + Interconnection Protocols: Part 12 - OS Security, Output + from the December 1994 Open Systems Environment + Implementors' Workshop (OIW)" + + SHA1 OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) oiw(14) secsig(3) + algorithm(2) 26 + } + + ASN.1 encoding: + 0x30, / * Universal, Constructed, Sequence * / + 0x21, / * Length 33 (bytes following) * / + 0x30, / * Universal, Constructed, Sequence * / + 0x09, / * Length 9 * / + 0x06, / * Universal, Primitive, object-identifier * / + 0x05, / * Length 5 * / + 43, / * 43 = ISO(1)*40 + 3 * / + 14, + 3, + 2, + 26, + 0x05, / * Universal, Primitive, NULL * / + 0x00, / * Length 0 * / + 0x04, / * Universal, Primitive, Octet string * / + 0x14 / * Length 20 * / + / * 20 SHA.1 digest bytes go here * / + + Cf. "A Layman's Guide to a Subset of ASN.1, BER, and DER -- + An RSA Laboratories Technical Note" by Burton S. Kaliski Jr. + Revised November 1, 1993 + */ + #endif /* SHA1 */ /* This many bytes from the end, there's a zero byte */ #define ASN_ZERO_END 3 *************** *** 263,272 **** --- 304,328 ---- i = make_RSA_PRIVATE_KEY(&PrivKey, E, D, P, Q, DP, DQ, U, N); if (i < 0) goto Cleanup; + #ifdef SHA1 + if (bytes == 20) { + memcpy(p, sha1_asn_array, sizeof(sha1_asn_array)); /* ASN data */ + p += sizeof(sha1_asn_array); + } else { + #endif memcpy(p, asn_array, sizeof(asn_array)); /* ASN data */ p += sizeof(asn_array); + #ifdef SHA1 + } + #endif memcpy(p, inbuf, bytes); /* User data */ /* Pad and encrypt */ + #ifdef SHA1 + if (bytes == 20) + i = RSAPrivateEncrypt((byte *)temp, &blocksize, + (byte *)temp, bytes+sizeof(sha1_asn_array), &PrivKey); + else + #endif i = RSAPrivateEncrypt((byte *)temp, &blocksize, (byte *)temp, bytes+sizeof(asn_array), &PrivKey); burn(PrivKey); *************** *** 322,331 **** --- 378,397 ---- front = (byte *)temp; back = front+blocksize; + #ifdef SHA1 + if (memcmp(front, asn_array, sizeof(asn_array))) { + if (memcmp(front, sha1_asn_array, sizeof(sha1_asn_array))) { + mp_burn(temp); + return -7; + } + front += sizeof(sha1_asn_array); + } else + #else if (memcmp(front, asn_array, sizeof(asn_array))) { mp_burn(temp); return -7; } + #endif front += sizeof(asn_array); /* We're done - copy user data to outbuf */