141 103 33MB
English Pages [944] Year 1995
a
ey
weiesrrtt a y
sft tii
aay ig
te
:
ie
i
i ieee ait !
et
:
. it
i
ior
Ba
Ua he ay Ai uray
Lua nt is ais
ie
tise, i ita ais
Le ae : st
Fen
in
Sees
ia
i
aeeearsese ieee Peibsase
i af
fta
satstenes
SESS os hitoh iit i
{oneit iFiis ru
LE
a
| ae _ :ath Seneca
ai
ee
rb
ehece
= Stacee
uae
a
MONTANA STATE _.. LIBRAR
Cee
ats
eWee
Ss
tY
coum, t DHEA
=
pee
bcd tae Fahe hy I nd gl = Oren
7g)
PGP
Source
Code
and Internals
Digitized by the Internet Archive in 2023 with funding from Kahle/Austin Foundation
https://archive.org/details/ogosourcecodeintO000zimm
PGP
Source
Code
and Internals
Philip Zimmermann
The MIT Press Cambridge, Massachusetts
London, England
©1995 Philip Zimmermann
PGP is freely distributable. For detailed information on PGP licensing, distribution, copyrights, patents, trademarks, liability limitations, and export controls, see chapter 12 (“Legal Issues”) in The Official PGP User’s Guide, also published by The MIT*’Press.
“PGP”, “Pretty Good Privacy”, “Phil’s Pretty Good Software”, and the “Pretty Good” label for computer software and hardware products are all trademarks of Philip Zimmermann. This book was was printed and bound in the United States of America.
Library of Congress Cataloging-in-Publication Data Zimmermann, Philip (Philip R.) PGP source code and internals / Philip Zimmermann. p. cm. Includes indexes. ISBN 0-262-24039-4 (hc) 1. Telecommunication systems—Security measures—Data processing. 2. Data encryption (Computer science) 3. PGP (Computer file) 4. Electronic mail systems—Security measures—Data processing. i, Wake. MKSOZS 5225.8 L995 005.8'2—dc20 95-15916 CIP
top ipets) KD \495°
Contents RE GLaC Orme
COGS
ee, oe
St TUCUIOL Smart te
| OAM IG IES DIED
erence ee
ne
WS) acer
peMORORLLGRMSGC.©or
ae
ne
tn
eens
atte helt,
USNDESe822 «ccs nin.edges ted a
a
Lee
ene Tne
perk let
tne
a dir
POLE
Cra Penns / oth ect 4... cor cee ee as cucu. dee meas
FH
maps pedate
MILE
pepe p mak
PMIGE mee PAM Ee
COD Um
VO
ae
19
ae
25
eee
26
ee
30 ne
SOG GMarn tere
TN COS OD OMS
mA
oe
ee
te ee
en
oi
65
66
ren ata arena Cemirrmgr het eB ear MAE MC Aves nats NBR bse ole ok
70
a ese inch be Gk
eae
aN
OE Fe
ees
Nae
ALE t4 Sir
be eG RADE TUR LETTS Vere ee Mae |e
ot bons teases ASST
er eneMe mean
PPL TEC Oe Mette
ue eR Aerie
re a UPS
a ares cents acti ir iaetre: Scene
hens eee
ee hi
Sy devonSidae ond Rie ee Dae
Onn ae ip
a ne
reir
ie
eee
76
eee
aA lite
tg
ot Run suereveuer eiciara raeretney et
oe 3 Labul fafasieue adn
ne
ne
iets ie Sn recevsv hs ecsecevos oc dw gealela ts erovenenn o¢ oe ian
Ee Pome tOUOaera) chs bola dee so eiiee eke eel dG bh ol kaha PaneHauer ec eee
31
ee
eC CCCs 2482 wae an
aa RA a LAL nla MCL RUSS
DTT |
eee
cc os ae Ser nae. ees tg ke ieee tn ote OPC
CLEIY ODL Mee
PALE MOS OSSOMOUR TANS: G2
HAE
18
setae e nein tree Ge een Nn wens On ee Ce
ts nite
PLAGE ©TATOO.»
Tih
ee
DED DW DeMaAK ir eon op) pci. esp cpitieadd unwise tos wre oe elder
Elie Wo bd COQUURSan ne
PEN
Ws
eevee
Nn
eee Te
1
ce
a
aw rere (ian er tee i
pe oats coos mee Ghee
ane te
EMU Mev axemarceee
PSU
Gee ton ener
bt
13
ee
RE
Ap te frais. PMet ¢ f.55 .< Sawing ot evans Coc pewes siertert rey eet
Xxill
re
Panta oe ee oe
ae
ess ei
eae
MRLea Pvdevvdslok She 9s
MC OGUR 2D Meer te koe
x1x
eee
gr aie cern x bane
en nt ene
DAU
car ae
eee
ann) Ree
rte iene teaA Aa eT
ee
oe eee
ioe cco a
85
96
em ene teas 100
eee
107
Gie ¢ se eO EPR meReeeees 7 122
23 0c8 ops coca nee
162
vl
FILE:
Sra GCLUES MIs, c i.Siacsee nikoe » SalDene RO boo vie Cath GPOTS
FILE:
s2matchvasm ey.,20.2 stale: Serer eee
BILE:
Sarmonsh
FILE:
SA MMOL Cyril cach seve eit eeUaye Soe a on Seta a iece eo et ae ene 174 TCE CUD Cheers, oe.Ferg aoe eT tls Fee ee cee, Deeg ce so. ea 176 CLEDY LEST Te, ONAL ESTE ACA) EIR REISER BEM, olla dake 17% EL SCLC EEOe Pot. CS ae eon ae a ete Saas Oe 2 Ding eUNtersn tare en een i i CLSOC RCs ree 2 totais ot. IUCN lig el O SonSoG OMaR rn a 178 Olt crCrete re Ane ented ieee aa ae ee SS Ne ee es ees 178
teem. 4.5. peel
Mune Plena
is eee PP A
ee)
054 oy ae «ee
ee, Ee
ee ie ee
ag Cea
ee
164
os bo ee
Pes
se Teta
167
on. salon
a
173
aay eee ee
SKIP MNO seM ieee mm den Rocke eotceeiemane ch LEGA deb e8 Feeney A ee eee coe COPVUNG a5 se ee ee eee eee Eger et ees een 2 een get lin Cee Pe Bb ocsounes a dchuee banner soo ahead paaaieh Pano. een
PolmaT
imionlin erate
SENG NC le Con RAENUTUem I ULLOL ese
atts Shere
ges 64
ein ec
Pode
ee
etn re a oo eee al eee ee ae. os 2iic hota ss sein etahice cid a.tsar inn ECR,
CONUS ee Pr
Ad
oo Sols
Ms
SIDING AGCT Sime
Vick dese ce ky fo MM
eke es Oe
iseader linet Ailend: csuetitele A dteietitt aS
ec Nae ha
aPTIOLCCCONE ama. dz-murer sex Rrurtee
at: wma
ee
ie
i
nena eed te
teeetles. «kWh
eee
re ee
A
182
184 188
190
ene eee
642 eet»
179 180 181
189
te: see
ENON os cone on
179
191
SOR
oes 192
SWAT ITLL PLO rms catce Care vtec raceh eae ce, «Nay neeoe ae Rk! ARs ae some Garinor tilege canes ence Jobe hey oe dco ae eho is ee le A ee
LOG 197
Rema EMIOTAT Grams 2.o07 Pas. cu
201
ADSA8 >6108) wd1 pana eae eo
atSeeelon AION SERRE BEMIL
a
Cee
ne
ee
6 Eat, At
Recent
ei
POW SCI
oe
Secret
eva
ee
aeRO
Ne 201
aire
FILE:
RCO BL Se Diet
FILE:
ONAL GO Ge ie Areysees sates2s Grp tase crn yaad
NORE RE Cael ee SLCC ene tre wind tgrdas Padah OREM egestas ae ee
751 751
FILE:
"Stdla pen’ 23¢ 200 tb ero last
752
eee
ee
ee
ee
MUI
eeeyeomi a. fo.
an dns
STARE OPSCSI
SECON
FULE Sfayis om «6s nnn wek nah era EnenS ents CE RIOT ERED
RA Ea
Ae
ete
/REARA CIRCUS
URN ET EMM Ee Fee
OE
4 2 sed
2%"
753
754
tt a eaeeaeanna PERE EA Rath easing ns tao ti ois RR sigl RMA soe Cha vik. Scab is wad bao ido MM ae ie rece A calae ee ASS GT Tere adts CAME eRe Ts eee ad Se eee Cine ce as Ba eM eo ELT aL UTE it ate oc ri. eg a ROP a Sik i eeaneaerenaeS SARA RAEGEL AAS Ca RELA AAEAE SOA Ca BEE patie icy ceo taornce tise asa ups a eae ieee Ome es Pees Feige treceter center cece tgtascareecsoes cceccess 1} RERUN ge Fea aan pCR ona oeria stot ane e aadine 8 eRe Aga 3 ees eee cee caer een ee ee Pe REGRD ease alo oe ee cee PE aa oe oe TORN Nic catia CORR ee Fate Pe ie ee Ea ee cs cara eda ember CaN Stee ae Ren ne ey ee pe Ee rece a aa rt ca SE RTL DOE EERE 19°" DLR eD RIE Te eS, BE igs ee EN Le
756 757 758 758 759 759 759 760 761 761 761 762 762 762 765 766 767 769
pee Pitch bead Bene a rhe UIT SE pS Gg Se LL de eee a
al i 772 774 776 ata
Boel
A t et tuts ticfs cuetek ea tected ee ono
Ee
ee a
aaa a
gira gerreigtee
Pe conerate Neate (i. fal wey tatiana
Pies
UE
em
re
GSA
Be
aaah DN Saf okAPLEN Covel 2 LOTTA BEN AMRR
ee
Pere NE ey Cy ty | ae TELIRSS te seein Be
ee
EMT AERIGR oy oo
pe
at ee te eo s uaaGeM ta Minin Sone ye rey ei a Pirie eae eeepc eee a CM cae agen magia ee ee ee eee ae
eee
etn eet
eae ant ail ia
et ss acd
Ne
a gelled cN
kee
a ee ee en ee Oe OES | eae
RECRIT
ame Rechteae bet ae Melani
ng aes Apa Moko
23 £5.10 5.2. noe Jek EEG sales Sore naa
rin tricn onion ae ate Aaa a Saar ROC IE
a x,
Be
acta ee ae
ace ae
ee
ee
i Migin iets ES eh dk rade ec eee
dee
780 ne 782
135
787 ie tI
ln sansncn re aheens eee aMPPEPERE ae IDS T eee SP.
oe vegunicece a,nico oda TVLO Delete meer ec oe a lamin cr ee 2 I
SANGHire
Lovattal 778
en
eae eG te
ee
aI 791 ae
792
ison
195
ie
ot ie
nego ee me nee aieore Or Aa
195 795
Xvi
FILE:
SA TE
BCE ore adenkitatehanersdiereraiannl orcuunrarevsiellenpht oboe arenanokost etek Ala exc te Raa
Bhi MR
NIM oss
oe om
cndec ceelvvnchonre decpncattoeckeciacell paces ee
Bene DibSe EP aco. scos-
iad
vet
=
ire
aa _
-
4
Ap dee
7
4,).i-8
RE T
i
_
n
cecehuaebes@
(co
rhea
wee
ia
:
a
poe ~
=
assen esi Yi
ee
PES
aiverall s-1te
-O
aie
eevee
Oe
-
a :
ee
—
00
f
Santaet
=
€ “7
el =
pearance aD aireovtees sy Hea eaeee :«
i
=
.
.
Mel
~~
=p) &@Os>-.
POR ES Cet
=
64808 -
eee
i
,
ad ee are
bedi
:
[vw
: +29 4 5@a ve “yi ~
i
——
Per eee ee
FN
=
aed
i
:
Be
-
ek ee
ee
:
ae sep en
oe ib eaben s
re
a
7 pred av Sond
webesiuis
“PSe- 0 ngs
2
til
aa
hile
_
2
Preface This book contains all of the C source code to a software package
called PGP (Pretty Good Privacy).
PGP is the most widely used
software in the the world for the encryption of electronic mail. It uses public key cryptography to let you communicate securely with people you’ve never met, without the prior exchange of keys over secure channels. Why publish an entire book (and a big one at that) comprised mainly of boring source code for a computer program? Well, there are some really good reasons. It concerns your civil liberties and poauies a bit of explaining, but it’s Bema quite an interesting story. Cryptography is a surprisingly political technology. In recent years, it has become more so min the controversy surrounding the Government’s Clipper i, the FBI wiretap legislation, export controls on cryptographic software, and the balance of power between a government and its people. Historically, cryptography has been used mainly by governments for diplomatic and military traffic. But with the coming of the information age, ubiquitous personal computers, modems, and fax machines, this is changing. With an emerging global economy depending more and more on digital communication, ordinary people and companies need cryptography to protect their everyday communications. Law enforcement and intelligence peace want access to all of our communications, to catch people who break the law, and detect threats to National Security. Civil libertarians want to keep the Government out of our private communications, to protect our privacy and maintain a healthy democracy. PGP is free software. Anyone may download it on the Internet, or from many Bulletin Board Systems. It has stirred up some controversy, because it has become a worldwide de facto standard for e-mail encryption, despite United States export restrictions. Initially published in the US, this package has spread by the diffusion that is common to free software packages, with its “forbidden” flavor giving it an extra popularity lick. Oddly enough, the US Government may have inadvertantly contributed to PGP’s spread by making it more popular because of my case. I am under criminal investigation as a result of PGP’s spread overseas, which the Government holds is in violation of US export restrictions. My case has captured a lotof press attention, in part because journalists realize that if an American can be imprisoned for electronically publishing something in the United States then journalists may themselves be at risk in tomorrow’s world of electronic newspapers on the information highway. Another reason the press is so interested in my case is the Government’s attempts to suppress public access to strong cryptography.
The Clinton administration is trying to get the phone companies to put a special encryption device into every telephone. They eXpect it to take many years to accomplish this. When this “Clipper chip”, as it’s called, is manufactured by the Government, they place a unique encryption key in each chip and keep a copy of the keys in
Preface
a vast government database, for wiretap purposes. Your telephone will someday have Big Brother inside. The Government hopes that the American public will accept this government-controlled cryptography and is trying to discourage other forms of cryptography they do not control. One way they discourage it is by the use of export restrictions on cryptographic software. This draws PGP into the press spotlight. The US State Department has a list of items that may not be exported without a license. The Munitions List. Mostly weapons, but included in that is encryption software. Encryption software may not be exported without a license, and that license is hard to come by if the software uses advanced encryption techniques that the Government can’t easily break. Software like PGP. The State Department allows items on the munitions list to be ex-
ported if they grant a Commodities Jurisdiction (CJ) for it, allowing it to be handled under the jurisdiction of the Commerce Department instead of the State Department. A CJ allows the item to be legally exported from the United States. It would be politically difficult for the Government to prohibit the export of a book that anyone may find in a public library or a bookstore. The State Department has already granted a CJ for another book containing cryptographic source code, oe Schneier’s Applied Cryptography. So, we’re putting the PGP source code in a book, which may be scanned in with optical
character recognition (OCR) software. And we are applying for a CJ. It will be interesting to see where this process leads. PGP uses the best encryption algorithms available in the open academic literature — the algorithms that have withstood the most peer review and are rooted in the best design principles of modern cryptography. PGP version 2.6.2 uses RSA for key management and digital signatures, the IDEA cipher for bulk data encryption, and MD5 for a secure one-way hash for digital signatures. And it compresses the data before encrypting it, using the ZIP algorithm. PGP was developed under difficult conditions, with no funding in a race against time in 1991 to get it out before it became illegal to publish software of this type. Senate Bill 266, the 1991 anti-crime bill, had a measure buried in it that foretold the shape of things to come. It was a “sense of Congress” resolution that said that communications system implementors should provide a way for the Government to obtain the plaintext contents of traffic. The resolution was defeated shortly after PGP was initially published, owing to public outcry from civil liberties groups. PGP was published as freeware, in an effort to preempt the possibility that the Government could suppress this technology later. There are other books in the computer science section of your bookstore that have source code examples of various algorithms. These books teach good programming style by providing good code
examples. This book is mostly not like that. Ar aaa some instructive examples of how to implement certain one might observe that this body of source code is not ample of clean modularity. The code is the way it is.
it does have algorithms, the best exThe trying
Preface
Xxl
conditions of PGP’s development led to expedient approaches to implementation, sometimes at a cost of elegance. Global variables are used more than they should be, there are many cases of redundant code, and there are many intermodule dependencies. As other software engineers all over the world contributed their own development efforts to PGP after version 1.0 was published in 1991, they inherited a misshapen crystal nucleus to accrete more code onto, and modified and remodified the code under pressures of expedience. Very little of my original code remains in PGP, mostly comprised of the multiprecision integer library, which I first wrote in late 1986. It is unfortunate that cleaner examples of code from my 20-year career as a software engineer could not have served as a basis for what would eventually become such a widely distributed body of source code that so many other programmers would look at. Despite the inelegance of the code, the quality of the cryptography and key management is very good, good enough to make a mark upon the world in such a way that no other cryptography software ever has, mpeeu ne some elements of the US Government as well as a number of foreign governments. PGP would not be where it is today without the volunteer efforts of many talented programmers from all over the world. Peter Gutmann and Branko Lankester contributed much effort to PGP development. Jean-loup Gailly contributed his ZIP compression routines. Many others contributed code, and they are named in the comments of the source code. Other people contributed their pee eae efforts to the PGP project, including my own legal defense team, suc as Phil Dubois, Eben Moglen, Ken Bass, and Curt Karnow. Other lawyers who provided legal advice include Tom Nolan and Chuck Marson. I’m writing some of this preface in the air between Bucharest and Budapest, on a speaking tour about privacy in the information age. In Bucharest, I saw the terrible legacy of a system designed by men who craved certainty, not trusting the people with individual freedom. Those men would have loved the Clipper chip. The people there now are glad to have their freedom, and they understand my concern about the power of Government. They already get it — and they don’t understand why we Americans don’t. A book comprised entirely of thousands of lines of source code looks pretty dull. But, then, so does a nondescript fragment of concrete — unless it happens to be a piece of the Berlin Wall, which many people display on their mantles as a symbol of freedom opening up for millions of Hee le. Perhaps in the long run, this book will hele open up the US borders to the free flow of information.
Philip R. Zimmermann Boulder, Colorado December 1994
ral Paes cages =
ugée
ERR AD beam 1? om Ce er pe
‘ rr
Pee
hen or
Secret”
i
» wend te
aaa
+o
ee af
Were
a
ath; SAH
©os
[oS tees ‘the sete x Fu? wor Gove cow
a «ats
aw
Sew
4b : eS ane
i.
bealhit
“asa
pe
=
adh
|)!
ie
HEM Muss
6 OO
O27 ts hevrvog
bo beady , tpt
sys wee aot
wre @
oF
ets
y ret eT EP
—_—
a
as.teenth 7}red haat cab; 4
y
ws
:
ee
vt teade
—— a
wee
iyi
al
Ce ;
w
it a.
J
ve
he
as -.
a
a
eb walt eh
je
"4
nh 5
“The
:
wr
Ot
it; +
"a
in ast
dione? Pe .
deh
reo velquil
ot
: “rh
®
fheasanls
-
iqail Al ks rm
i aera erie Wh sis PS BPE (ae
bart),
vadpcr ot net bie asar ea0dT
ieootlihrerGe?
rea
Area
.
‘bag
ero nd
—— epee nipe i.a buarebo pF Paig S| a, i? ihn ark beso aon
cay jhobtctt Wind.
pO:
eet
fre Orie leee Yat
cy
A & a0
Jee
keg rendts
eS TPn TR Epi
en
imoe
Pi
ia ithe vi hortlt , eu Chee ta
bares! ot “Sehwe ooreys Gas
o
Saat
&
Aer: OF: aa
Sram
Af)
‘
Me
rite 7
ms
legs. ike
ae
eo
tye
7 -
*
i
OCR Instructions We offer the following suggestions for best optical character recog-
nition (OCR) results, whether with freeware OCR or with one of the commercial products.
Use a good scanner set to at least 300 dpi resolution. Scan from the original pages rather than from photocopies. Avoid any page rotation on the scanner. Re ewN Follow the instructions in your OCR product manual. If you are considering a commercial product, the University of Nevada at Las Vegas has rated several of the commercial systems. Based on their ratings, either Calera Recognition Systems or Expervision product offerings should give satisfactory recognition on these pages. For either of these products, edit the resulting recognition files and save them after cleanup as ASCII before attempting to compile.
Free OCR There are a small number of shareware and PD OCR programs. Unfortunately, none of them will cut it for OCRing this book. They are: CalPoly OCR Library PD, source form, buggy and slow. ProCR by David P. Gray Shareware for DOS, poor accuracy. OCRShare from Solution Technologies Shareware for DOS, no scanner and bad image format support.
Reconstituting Files Usually, OCR programs start by scanning each page into a separate image file, and then produce a text file corresponding to each image file. The files get names that convey the order they were scanned in. If you scan and OCR the files in order, you should be able to reconstitute the files by looking for the “New File” comment
strings found throughout the book. If you are familiar with a text processing language such as AWK, you will be able to process the files in batch mode.
Sree
“toda culls AYE
_
;
i
~
: 7
;
6
teri
at
ee { bie yd cae rad erie geOO, pe fe wade
‘ =.
-
Saliy ee ward. arth ee
get
«quar tat hee venoan
tate
oF
a
‘on
a
ste ng ogg
-
v=, sali aurusioaaeons ou &
tact ft wire
«
oA) own
fone wince
We Fiat anaes
yal yoqeerios ol? txat @ esbog Bayt
atl Meats oy
Te
io
(arm
j
%@
Th)
hea
‘an — ane off
eaTithiy
>
°S
At all ey BOY hype en pas ie a
Seinen? “fT? esi oni 4 ds a pom
att rut patho of belt of) siitiiiaeeras hy nes) heed wt twoureia® hare
poll a2) deeesiy
de od Wo oire We
02
em
Ao sengQgnnl
abut
PGP
Source
Code
and Internals
=
File:
‘makefile’
4 Pile +*
makefi le2
(New File)
Makefile
for PGP
(unix)
Most MS-DOS make utilities are a Makefile as complex as this, PGP 2.6.1 can routines that
lobotomized so they cannot cope so MS-DOS is not included here.
be compiled to use either come with RSAREF or those
multiprecision
library
(mpilib)
that
with
the modular exponentiation that are built into the
comes
with PGP.
For UNIX machines
(and probably VAX/VMS, too), we recommend using the RSAREF routines. For MSDOS, we recommend using the mpilib routines (there are assembly language routines that mpilib can call under MSDOS making it much faster than the C code in RSAREF). To use the mpilib routines, you should: (1) make sure you have the version of RSAREF that comes with
the PGP 2.6.1 distribution, in this makefile, add the compiler
(2)
CFLAGS
(3) Note:
for
your
system
switch
-DUSEMPILIB
to
below,
in the RSAREF makefile, add the compiler switch -DUSEMPILIB to CFLAGS before building RSAREF.
when
you
build
RSAREF
with
-DUSEMPILIB,
fail to link, because they will be unable exponentiation routines. This is OK. Alternatively, to build PGP 2.6.1 (1) you can use any version of
rdemo
to find
and
dhdemo
will
the modular
with the RSAREF exponentiation routines, of the March 16, 1994 distribution
RSAREF.
(2) you need not modify this makefile, (3) you need not modify the RSAREF makefile. Note: If your system does not have memmove, then you should to OBJS_EXT for your rule and send that in as a bug for your CFLAGS
add memmove.o platform.
options:
-DHIGHFIRST -DDEBUG -DNOTERMIO
if building PGP on a big-endian system to include debugging information if your system has no termios
-DSVR2 -DDYN_ALLOC -DSMALL_MEM -DIDEA32
for System V release 2 if your compiler does not support large static arrays if your machine has a small memory (required for MSDOS) if your int’s are 32 bits this is probably faster
-DPORTABLE -DMPORTABLE
and to build the portable version of the (ie if no optimized asm versions are
RSA primitives available)
Define one of: +H HH HHHHHHHHRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
—-DMERRITT
Merritt’s
-DPEASANT -DUPTON -DSMITH See also the
Russian peasant modulo multiply algorithm use Upton’s modmult algorithm use Smith’s modmult file platform.h for system defaults
modmult
If you don’t
have
a working
(fast on risc machines)
FIONREAD
ioctl
you must
use
one
of these:
-DUSE_SELECT to use select() system call -DUSE_NBIO to use non-blocking read() H HH HHHHAHAH CFLAGS=
-O
-DUNIX
-DPORTABLE
# must set byte order for # BYTEORDER= -DHIGHFIRST CG
=
cc
LD LDFLAGS CPP DBG
= = = =
(Xe
=
targets
# Link
$(CC) -0
and
"bsd"
command
$(CC)
for
old
versions
-c
of
make
# Assembler
OBJS_EXT= LIBS_EXT=
PROJ
"sysv"
-E
# uncomment this #MAKE = make
ASM
$(BYTEORDER)
command
# ASM obj. files # Libararies
= pgp
default:
all:
@echo @echo
''To build PGP "' make
@echo
""
@echo @echo
"where can be:" " 386bsd, 3b1, 3b1_asm, amix-68k-gcc,
@echo
" bsdgcc,
@echo @echo
" hpux-68k-gcc, hpux-pa(*), hpux-pa-ansi, hpux-pa-gec," "' hpux9-pa-ansi, irix, irix_asm, isc, isc_asm, linux, machten,"'
@echo @echo @echo
" mach_386, mips-ultrix, netbsd, newsasm, newsgcc, next," '' next486, nextHP, os2, osf, qnx4 , rs6000, rt_aos4,"' " sco-2.0, sgigcc, sgigcc_asm, solx86gcc, sun386i, sun3asm,"
@echo
" sun3cc(*),
@echo
"'
@echo
" vax_bsd43,
@echo
""
@echo
"For targets marked
@echo
"See
$(PROJ)
on your flavour "'
djgpp,
sun4acc,
encore,
sun3gcc,
hpux-68k(*),
sun4cc(*),
sun4sunosS5acc,
x286(*),
setup.doc
for
of Unix,
sunspc,
type:"
aux(*), aux-gcec, hpux-68k-ansi,"
sun4gcc,
bsd,"
sun4sunos5gcc,"
sysv_386,
vax-ultrix,"
xenix386"
with
(*) you must
further
details."
first
get unproto."
#
File:
‘makefile’
# For a pure MPILIB version, #RSALIBS #RSAOBJS rsagluel.o # For
an
RSADIR
RSAREF
=
version,
uncomment
the
the following
following
lines
lines
2 2/rsaret
RSALIBDIR RSAINCDIR RSALIBS RSAOBJS
= $(RSADIR)/install/unix = -I$(RSADIR)/source -I$(RSADIR)/test
$(USEMPILIB)
= $(RSALIBDIR)/rsaref.a = rsaglue2.o
# If you want to use MPILIB USEMPILIB = -DUSEMPILIB
# Assembly-language
_80386.0: $(CPP) $(ASM) rail
8086.0:
uncomment
=s2
as
subroutine
a back
end to RSAREF,
uncomment
dependencies
80386.S $(ASMDEF) 80386.S -o $@ _80386.s
> _80386.s
_sHOSEIS., S
8086.asm
cp
8086.asm
8086.s
$(ASM) -o $@ 8086.s TMe—-teoOSomS _zmatch.o:
zmatch.S
$(CPP) $(ASM) rm
-f
$(ASMDEF) zmatch.S -o $0 _zmatch.s
> _zmatch.s
_zmatch.s
sparc.o:
sparc.s
$(CPP) $(ASM) rest
$(ASMDEF) sparc.S -o $@ _sparc.s
| grep -v
’°#
’ > _sparc.s
Ssparces
#mc68020.0:
#
$(CC)
ZIPOBJS=
zbits.o zdeflate.o zfile_io.o zglobals.o \ zinflate.o zip.o zipup.o ztrees.o zunzip.o
OBJ1
pgp.o crypto.o keymgmt.o fileio.o \ mdfile.o more.o armor.o mpilib.o mpiio.o \ genprime.o rsagen.o random.o idea.o passwd.o \ md5.o system.o language.o getopt.o keyadd.o \ config.o keymaint.o charset.o \ randpool.o noise.o
=
OBJS =
-c
mc68020.S
$(OBJ1) $(ZIPOBJS) $(RSAOBJS) $(OBJS_EXT)
this
line:
CFLAGS
= $(CFLAGS)
$(PROJ):
-I$(RSAINCDIR)
$(OBJS)
$(LD) # Commodore Amiga amix-68k-gcc:
$(MAKE)
-o $(PROJ)
Running
$(OBJS)
SVR4
2.ip2a
$(LDFLAGS)
with
GCC
$(LIBS_EXT)
2.6.0
$(RSALIBS)
LER
all CC=gcec LD=gcc \
CFLAGS="$(RSAINCDIR) -DPORTABLE —-DIDEA32"
-O02 -DHIGHFIRST
-DUNIX
\
linux:
$(MAKE)
all CC=gcc LD=gcc
CFLAGS="$(RSAINCDIR)
-06
OBJS_EXT="_80386.0 -g3 -DUNIX
-DIDEA32
_zmatch.o"
\
-DASM"
386bsd:
$(MAKE)
all CC=gcc LD=gcc
CFLAGS="$(RSAINCDIR)
OBJS_EXT=""_80386.0
-O -DUNIX
-DIDEA32
-DASM
_zmatch.o"
\
-DMAX_NAMELEN=255"
netbsd:
$(MAKE)
all CC=gcc LD=gcc
CFLAGS="$(RSAINCDIR)
# Sun 3 with gcc # change -traditional-cpp sun3gcc:
-O
OBJS_EXT="_80386.0
-DUNIX
-DIDEA32
to -traditional
_zmatch.o"
-DASM
for gcc
\
-DMAX_NAMELEN=255"
< 2.0
$(MAKE) all CC=gcc LD=gcc OBJS_EXT=memmove.o \ CFLAGS="$(RSAINCDIR) -O -traditional-cpp -DUNIX -DIDEA32 -DPORTABLE"
-DHIGHFIRST
\
sun3asm:
$(MAKE)
all CC=gcc LD=gcc
CFLAGS="$(RSAINCDIR)
# Sun
3 with
sun3cc:
standard
cc:
compile
with
memmove.o"
-DUNIX
# Sun 4 SPARC
\
-DHIGHFIRST
-DHIGHFIRST
\
-DPORTABLE"
with
gcc
(tested
# used with older versions -traditional-cpp
with
of gcc)
gcc
1.39
to -traditional
and newer,
for gcc
sparc.s
can
sun4cc:
with
standard
cc:
compile
with
not
be
< 2.0
$(MAKE) all CC=gcc LD=gcc OBJS_EXT="sparc.o memmove.o" \ CFLAGS=""$(RSAINCDIR) -O -traditional-cpp -DUNIX -DHIGHFIRST # Sun 4 SPARC
-DIDEA32"
unproto
unproto/cpp $(MAKE) all CC=cc LD=cc OBJS_EXT=memmove.o \ CFLAGS="$(RSAINCDIR) -Qpath unproto -O -DUNIX -DIDEA32
# change sun4gcc:
OBJS_EXT="mc68020.0
-O -traditional-cpp
unproto
unproto/cpp $(MAKE) all CC=cc LD=cc OBJS_EXT="sparc.o memmove.o" \ CFLAGS="$(RSAINCDIR) -Qpath unproto -Dconst= -O -DUNIX \
-DIDEA32"
#
File:
‘makefile’
—-DHIGHFIRST
# Sun 4 running
-DIDEA32"
Sunos5
(Solaris).
sun4sunos5dgcc:
$(MAKE) all CC=gcec LD=we OBJS_EXT=sparc.o \ CFLAGS="$(RSAINCDIR) -O -traditional-cpp -DSOLARIS -DIDEA32"
# Sun 4 using sun4acc:
ASMDEF=-DSYSV
SunPro
$(MAKE)
# Sun 4 running
-DHIGHFIRST
\
C compiler
all CC=acc
CFLAGS=""-w
-DUNIX
LD=acc
$(RSAINCDIR)
SunOs
CPP="cc
-x04
5 CRY
-E" OBJS_EXT="sparc.o
-DUNIX
-DHIGHFIRST
using SunPro
memmove.o"
-DIDEA32"
\
\
C compiler
sun4sunosSacc:
$(MAKE)
all CC=cc
LD=gcec OBJS_EXT=sparc.o
CFLAGS=""-w $(RSAINCDIR) ASMDEF=-DSYSV
-x04
-DSOLARIS
\
-DUNIX
-DHIGHFIRST
-DIDEA32"
\
sun3861:
$(MAKE)
all
CC=gcc
LD=gcc
CFLAGS="$(RSAINCDIR) ASMDEF=-DSYSV
-I.
OBJS_EXT="_80386.0 -O
-DUNIX
-DIDEA32
memmove.o"
\
-DNOTERMIO"
\
sunspc:
$(MAKE)
all
CC="ccspce
-B/1.8.6/sun4
CFLAGS="$(RSAINCDIR)
-DMERRITT"
# x86 running
-O
-DUNIX
-ansi
-DIDEA32
-w -I/usr/include"
-DHIGHFIRST
-DUNIT32
\ \
OBJS_EXT=sparc.o
Sunos5
(Solaris)..
solx86gcc: $(MAKE) all CC=gcc LD=gcc OBJS_EXT=_80386.0 \ CFLAGS="$(RSAINCDIR) -O -traditional-cpp -DSOLARIS ASMDEF=-DSYSV
# Sony newsos v3 for m68k, with gcc # change -traditional-cpp to -traditional newsgcc:
$(MAKE)
all CC=gcc LD=gcc
with
gcc
-DIDEA32"
\
< 2.0
\
CFLAGS="$(RSAINCDIR) -O -I. -DUNIX -DHIGHFIRST -DIDEA32 #
for
-DUNIX
-traditional-cpp -DPORTABLE"
-DNOTERMIO
-D_BSD
\
asm
newsasm: $(MAKE) all CC=gcc LD=gcc OBJS_EXT=mc68020.s CFLAGS="$(RSAINCDIR) -O -I. -traditional-cpp -DNOTERMIO -D_BSD -DUNIX -DHIGHFIRST -DIDEA32"
qnx4:
$(MAKE)
all \
CFLAGS=""$(RSAINCDIR)
-DPORTABLE
-3
-DMPORTABLE
-O
-I.
-b
$(BYTEORDER)
-DNO_PARAM_H
-DUNIX
-DMAX_NAMELEN=255"'
-DIDEA32
\
\
encore:
$(MAKE) all -DMPORTABLE sysv:
CC=gcc LD=gcc CFLAGS="$(RSAINCDIR) -O -DUNIX -DUSE_NBIO -DIDEA32 -DUPTON -DHIGHFIRST"
-DPORTABLE
\
$(MAKE) all CPP=/lib/cpp \ CFLAGS="$(RSAINCDIR) -O -DUNIX -DPORTABLE -DUSE_NBIO $(BYTEORDER)"
# optimized version with 80386.5S sysv_386: $(MAKE) all CPP="/lib/cpp -DSYSV" OBJS_EXT="_80386.0 _zmatch.o" CFLAGS="$(RSAINCDIR) -O -DUNIX -DIDEA32 -DUSE_NBIO -DASM"
\
xenix386:
$(MAKE)
all CPP=/lib/cpp
CFLAGS="$(RSAINCDIR)
# Interactive
Unix
OBJS_EXT=""_80386.0
-O -DUNIX
SVR3/386
version
-DSVR2
_zmatch.o"
-DIDEA32
\
-DUSE_NBIO
-DASM"
3.2 with gcc
SICi:
$(MAKE)
all CC=gcc LD=gcc LDFLAGS="-lcposix
CFLAGS="$(RSAINCDIR)
-O
-DUNIX
-DIDEA32
-lrpc"
-DUSE_NBIO
OBJS_EXT=memmove.o -DPORTABLE
\
\
-DNO_ITIMER"
isc_asm:
$(MAKE)
all CC=gcc LD=gcc
CFLAGS="$(RSAINCDIR)
LDFLAGS="'~lcposix
OBJS_EXT=""_80386.0
-O -DUNIX
-DIDEA32
memmove.o"'
-DUSE_NBIO
ASMDEF=-DSYSV
-DNO_ITIMER"
\
\
-lrpc"
mach_386:
$(MAKE)
all CC=gcc LD=gcc
CFLAGS="$(RSAINCDIR)
CPP=/lib/cpp
-O -I.
-DMACH
OBJS_EXT=_80386.0
-DUNIX
-DIDEA32
\
-DNOTERMIO"
machten:
$(MAKE)
all
CC=gcc
LD=gcc
CFLAGS="$(RSAINCDIR)
-DIDEA32
-O
CPP=/lib/cpp
-I.
-DMACH
OBJS_EXT=mc68020.0
-DUNIX
-DHIGHFIRST
\
\
-DNOTERMIO"
SiCOm 2m): $(MAKE) all CC=gcc LD=gcc CPP=/usr/lib/xcpp ASMDEF=-DSYSV CFLAGS="$(RSAINCDIR) -Dsco -O
# Xenix x286:
OBJS_EXT=_80386.0 \ -DUNIX -DIDEA32 -DUSE_NBIO"
286 $(MAKE) all CC="sh ccc.x286 -M21" LD="cc -M21" ASM=""cc -M21" OBJS_EXT=8086.0 LDFLAGS=""-F 3000" \ CFLAGS="$(RSAINCDIR) -LARGE -Ot -DUNIX -DNOPROTO -DSMALL_MEM -DDYN_ALLOC -DUSE_NBIO -DSVR2"
ce INDY SES aix386:
Wal. 3
\ \
#
File:
‘makefile’
$(MAKE) all CPP="/lib/cpp -DSYSV" \ CFLAGS="$(RSAINCDIR) -O -DUNIX -DIDEA32 -DUSE_NBIO -DSYSV -DPORTABLE" # AIX/370
(like general
SysV)
aix370:
$(MAKE)
all CPP=/lib/cpp \
CFLAGS="$(RSAINCDIR) -DPORTABLE"
-O -DUNIX
-DIDEA32
-DUSE_NBIO
-DSYSV
-DHIGHFIRST
\
3b1:
$(MAKE)
all CC=gcc LD=gcc CPP=/usr/lib/cpp \
CFLAGS="$(RSAINCDIR) -O -I. -DUNIX —-DHIGHFIRST -DMAX_NAMELEN=14"
-DSVR2
-DPORTABLE
-DUSE_NBIO
\
3bi_asm:
$(MAKE)
all CC=gcc LD=gcc
CFLAGS="$(RSAINCDIR) —-DMAX_NAMELEN=14"'
# Silicon sgigcc:
Graphics
Iris
-O
CPP=/usr/lib/cpp
-I.
-DUNIX
-DSVR2
OBJS_EXT=3b168010.0 -DUSE_NBIO
\
IRIX
$(MAKE) all CC=gcc LD=gcec CPP=/usr/lib/cpp \ CFLAGS="$(RSAINCDIR) -O -DUNIX -DPORTABLE -DUSE_NBIO # SGI with assembler sgigcc_asm:
\
-DHIGHFIRST
-DHIGHFIRST"
modules
$(MAKE) all CC=gcc LD=gcc CPP=/usr/lib/cpp OBJS_EXT="1r3000.0 CFLAGS="$(RSAINCDIR) -O -DUNIX -DUSE_NBIO -DHIGHFIRST"
r3kd.o"
\
arse
$GMAKE)
Malle GC=cc
LD=cc
CFLAGS=""$(RSAINCDIR)
-O
\ -DUNIX
-DPORTABLE
-DUSE_NBIO
-DHIGHFIRST
—acpp"
irix_asm:
$¢(MAKE) all CC=cc LD=cc CFLAGS="$(RSAINCDIR) -O
# Users
of PGP
# a snake hpux:
versions
(HP Series
will
expect
700 RISC machine).
a target
Don’t
’hpux’
disappoint
to build
-acpp"
for
them.
hpux-pa-ansi
# HP series 700 pa-risc # UNTESTED for PGP 2.5 hpux-pa-ansi:
.
pgp.rsp $(0BJ2)+ >>pgp.rsp $(0BJ3)+ >>pgp.rsp $(0BJ4)+ >>pgp.rsp $(0BJ5)+ >>pgp.rsp $(ZIPOBJS) >>pgp.rsp $(PROJ)$(EXT) >>pgp.rsp
echo
NUL.MAP
>>pgp.rsp
echo $(LIBS_EXT) $(RSALIBS); >>pgp.rsp
$(LD)
$(LDFLAGS)
OQpgp.rsp
## Dependencies ## armor.obj: armor.c mpilib.h usuals.h platform.h fileio.h mpiio.h language.h armor.obj: pgp.h more.h armor.h crypto.h charset.obj: charset.c usuals.h language.h charset.h system.h config.obj: config.c usuals.h fileio.h pgp.h more.h armor.h config.h charset.h crypto.obj: crypto.c mpilib.h usuals.h platform.h mpiio.h random.h idea.h crypto.obj: crypto.h keymgmt.h keymaint.h pgp.h more.h armor.h mdfile.h md5.h crypto.obj: fileio.h charset.h language.h exitpgp.h zipup.h rsaglue.h fileio.obj: fileio.c random.h usuals.h mpilib.h platform.h mpiio.h fileio.h fileio.obj: language.h pgp.h more.h armor.h exitpgp.h charset.h system.h genprime.obj: genprime.c mpilib.h usuals.h platform.h genprime.h random.h getopt.obj: getopt.c getopt.h idea.obj: idea.c idea.h usuals.h randpool.h keyadd.obj: keyadd.c mpilib.h usuals.h platform.h crypto.h fileio.h keymgmt.h keyadd.obj: charset.h language.h pgp.h more.h armor.h exitpgp.h keyadd.h keyadd.obj: keymaint.h keymaint.c mpilib.h usuals.h platform.h random.h keymaint.obj: crypto.h fileio.h keymgmt.h keymaint.h pgp.h more.h armor.h keymaint.obj: mpiio.h charset.h language.h keymgmt.obj: keymgmt.c system.h mpilib.h usuals.h platform.h idea.h random.h keymgmt.obj: crypto.h fileio.h keymgmt.h rsagen.h mpiio.h language.h pgp.h keymgmt.obj: more.h armor.h md5.h charset.h keymaint.h language.obj: language.c usuals.h fileio.h language.h pgp.h more.h armor.h language.obj: charset.h md5.obj: md5.c md5.h mdfile.obj: mdfile.c mpilib.h usuals.h platform.h mdfile.h md5.h fileio.h mdfile.obj: language.h pgp.h more.h armor.h more.obj: more.c mpilib.h usuals.h platform.h language.h fileio.h pgp.h more.h more.obj: armor.h charset.h mpiio.obj: mpiio.c mpilib.h usuals.h platform.h mpiio.h pgp.h more.h armor.h mpilib.obj: mpilib.c mpilib.h usuals.h platform.h noise.obj: noise.c usuals.h randpool.h noise.h
passwd.obj: passwd.c random.h usuals.h md5.h language.h pgp.h more.h armor.h pgp.obj: pgp.c system.h mpilib.h usuals.h platform.h random.h crypto.h fileio.h pgp.obj: keymgmt.h language.h pgp.h more.h armor.h exitpgp.h charset.h getopt.h pgp.obj: config.h keymaint.h keyadd.h rsaglue.h r3000.obj: r3000.c mpilib.h usuals.h platform.h lmul.h random.obj: random.c system.h idea.h usuals.h md5.h noise.h language.h random.h random.obj: fileio.h pgp.h more.h armor.h randpool.h randpool.obj: randpool.c randpool.h usuals.h md5.h rsagen.obj: rsagen.c mpilib.h usuals.h platform.h genprime.h rsagen.h random.h rsagen.obj: rsaglue.h rsagluel.obj: rsaglue1.c mpilib.h usuals.h platform.h mpiio.h pgp.h more.h rsaglueil.obj: armor.h rsaglue.h random.h rsaglue2.obj: rsaglue2.c mpilib.h usuals.h platform.h mpiio.h pgp.h more.h rsaglue2.obj: armor.h rsaglue.h random.h ../rsaref/install/global.h
rsaglue2.obj: rsaglue2.obj: rsaglue2.obj:
../rsaref/source/rsaref.h ../rsaref/source/md2.h ../rsaref/source/md5.h ../rsaref/source/des.h ../rsaref/source/rsa.h
sleep.obj: sleep.c system.obj: system.c exitpgp.h system.h usuals.h zbits.obj: zbits.c zip.h ztailor.h ziperr.h zdeflate.obj: zdeflate.c zunzip.h usuals.h system.h zip.h ztailor.h ziperr.h zfile_io.obj: zfile_io.c zunzip.h usuals.h system.h zglobals.obj: zglobals.c zip.h ztailor.h ziperr.h zinflate.obj: zinflate.c zunzip.h usuals.h system.h exitpgp.h zip.obj: zip.c usuals.h fileio.h language.h pgp.h more.h armor.h exitpgp.h Zip.obj: ziperr.h zipup.obj: zipup.c zip.h ztailor.h ziperr.h zrevisio.h ztrees.obj: ztrees.c zip.h ztailor.h ziperr.h zunzip.obj: zunzip.c zunzip.h usuals.h system.h
#
Ealiers
‘coe.
Her iler #
ef
Gee?
(New File)
#!/bin/sh # # script to a while
compile
ANSI
source
with
a K&R
:
do
case
$1 in
=c)
-—o) *.c) *)
ap
shift 3; break ;; arg="$arg
$1"
esac shift done set
-e
foal shift
b=‘basename
$f
.c‘
cc -E $arg $f | unproto/unproto cc -c $arg ${b}.i $* rm ${b}.i
>${b}.i
;;
compiler
and unproto.
!
18
ie AWWA #
revares 5 ia
(New File)
# # script # while do
to
compile
ANSI
source
with
a K&R
compiler
and unproto.
:
case
$1 in =c) -o) *.C) *)
a Ainsisdy 9 9 break ;; arg="$arg
$1"
;;
esac shift done set
-e
f=$1 shift b=‘basename
$f
.c‘
ce -E -C -1. $arg $f | unproto/unproto | \ sed ’s/-#[ ]+*\( [0-9] [0-9] *\)/#line \1 "’"\/tmp\/${b}.c'"?"/? cc -c $arg /tmp/${b}.c $* rm /tmp/${b}.c
>/tmp/${b}.c
File:
‘descrip.mms’
File:
its)
‘descrip.mms’
(New File) DESCRIP.MMS (c)
- MMS file
Copyright
1991-93
for PGP/VMS by Hugh Kennedy.
All
rights
reserved.
The author assumes no liability for damages resulting from the use of this software, even if the damage results from defects in this software. No warranty is expressed or implied. The above notwithstanding, a license to use this software is granted to anyone either in the original form or modified on condition that this notice is not removed. Options
Flags:
PGP_DEBUG PGP=GCC — PGP_RSADIR
Define Define -
Use
Modified: Adapted
to use
Change
for
new
method
change
Modified: Allow cm cam Come fam pam emus came fmm fem Sum cm cum cam pm sem fae tee tem fam sam mm cme
use
cleaner).
Date:
modules
for
for
from
for
release
11-Mar-1991 as
release
GCC
1.8.
Hugh A.J.
Kennedy.
Author:
Hugh A.J.
Kennedy
Author:
Hugh A.J.
Kennedy
1.7.
(use one
options
routine
file)
Author:
module
18-Sep-1992
string
Author:
a target.
Alphabetise
to private
directory.
1.3
25-Jun-1992
Date:
10
specified
8-Apr-1992
Date:
09
references
fixes
from
RSATST
of support
(again)
Modified: Misc
program,
from
21-Nov-1991
Date:
08
Modified:
Remove
modules
O07
Modified: All
new
harness
Modified:
Routines
Date:
04
test
Adapted
RSAREF
03
Modified: Add
if you want the debug version to use GNU C instead of VAX C
list
Author:
versions
Hugh A.J. for
ease
of
Hugh A.J.
- no
Kennedy. comparison.
Kennedy
longer reqd.
Date:
7-Nov-1992
Author:
Hugh A.J.
Kennedy
Date:
28-Jan-1993
Author:
Hugh A.J.
Kennedy
V2.01
11 of logicals
for
source
and object
directories
(keeps
things
|
'! ' '! ! ! ' ! !
Modified: Ammend
7?
dependencies
Modified: Update
Date: to
13
support
Add support
24-Feb-1993
include
Date:
for
GNU
for RSAREF
C.
new
header
Author:
Author:
as I live outside
PGP_COMPAT
VFLAGS = MD = MD4
,COMPATIBLE
.else
MD = MD5 . endif .ifdef
WFLAGS
XFLAGS ZFLAGS
= /define=($(WFLAGS) ) = /define=($(WFLAGS) , EXPORT ,NO_ASM,NOSTORE)
.else
ZFLAGS
=
$(CFLAGS)
/define=(EXPORT,NO_ASM,NOSTORE)
.endif
.ifdef CC
=
PGP_GCC
! Use
GNU
GCC
C_PATH_NAME .ifdef CCLIB
= C_INCLUDE_PATH
PGP_RSADIR =
,GNU_CC:
[000000]GCCLIB/1ib,
.else
CCLIB
GNU_CC: [000000] GCCLIB/1lib,
.endif .else
C_PATH_NAME
= C$INCLUDE
. endif
! ! Debugging !
Support
Hugh A.J.
Kennedy
dependencies.
(untested,
'
.ifdef
Kennedy
files.
10-May-1993
Fix
Hugh A.J.
CC
Compiler
the US).
!
File:
‘descrip.mms’
-ifdef
PGP_DEBUG
MFLAGS
= $(MFLAGS)
LINKFLAGS
/debug
= $(LINKFLAGS)
.ifdef
PGP_GCC
DFLAGS
= /DEBUG
/debug/exe=$(mms$target ) ! Are we debugging
.else
DFLAGS
Poa
! No,
Debugging
! Not
debugging
! Use
GCC w/o debug
AND using
with
VAX
GCC?
C
= /debug/noopt
. endif YFLAGS
= $(XFLAGS)
else
.ifdef
PGP_GCC
YFLAGS
= $(XFLAGS)
.else DFLAGS
! Use VAX C w/o debug = /opt=noinline
YFLAGS = $(XFLAGS) endif
LINKFLAGS
= /exe=$(mms$target )
.endif CFLAGS default
= $(CFLAGS)$(DFLAGS)$(YFLAGS ) : obj:pgp.exe ! do nothing... @
petal SiG if
f$trnlnm("src")
.eqs.
""
then
define
src
’f$environment ("default")?
if f$trninm("obj") .eqs. "" then define obj ’f$environment ("default") ’ if f$trnlnm("$(C_PATH_NAME)") .eqs. ""' then define $(C_PATH_NAME) SRC .last
'
deassign
$(C_PATH_NAME)
! RSAREF Stuff ! ifdef PGP_RSADIR
RSAOBJS
= obj:rsa.obj
obj:rsa.obj
obj:nn.obj
obj:r_random.obj
: $(PGP_RSADIR)rsa.c
src:global.h
$(PGP_RSADIR)r_random.h
obj:r_stdlib.obj
$(PGP_RSADIR)rsaref.h
$(PGP_RSADIR)md5.h
-
$(CC) obj:nn.obj
$(CFLAGS) /INCLUDE=(src,$(PGP_RSADIR) )/define=("static=") $(MMS$SOURCE) : $(PGP_RSADIR)nn.c src:global.h $(PGP_RSADIR)rsaref.h $(PGP_RSADIR)digit.h $(CC) $(CFLAGS) /INCLUDE=(src,$(PGP_RSADIR)) $(MMS$SOURCE) obj:digit.obj : $(PGP_RSADIR)digit.c src:global.h $(PGP_RSADIR)rsaref.h $(PGP_RSADIR)nn.h $(PGP_RSADIR)digit.h $(CC) $(CFLAGS) /INCLUDE=(src,$(PGP_RSADIR)) $(MMS$SOURCE) obj:r_random.obj : $(PGP_RSADIR)r_random.c src:global.h $(PGP_RSADIR)rsaref.h
$(PGP_RSADIR)r_random.h
$(PGP_RSADIR)md5.h
$(CC) $(CFLAGS) /INCLUDE=(src,$(PGP_RSADIR) )/define=("static=") obj:r_stdlib.obj : $(PGP_RSADIR)r_stdlib.c srce:global.h $(PGP_RSADIR)rsaref.h $(CC) $(CFLAGS) /INCLUDE=(src,$(PGP_RSADIR) )/define=("static=")
$(MMS$SOURCE) $(MMS$SOURCE)
. endif
ieZieaocurt ' ZIPOBJS = obj:zbits.obj obj:zdeflate.obj obj:zglobals.obj obj:zinflate.obj obj:zip.obj obj:zipup.obj obj:zfile_io.obj obj:ztrees.obj obj:zunzip.obj ZIPH= @esrc:zrevisio.h srce:ztailor.h sre:zunzip.h sre:zip.h src: zipere-n obj-zbits.obj,: sres:zbits.c $(ZIPH)
$(CC) $(DFLAGS) $(ZFLAGS) $(mms$source)
obj:zdeflate.obj
$(CC)
obj:zfile_io.obj
$(CC)
obj:zglobals.obj
$(CC)
$(CC)
obj:zipup.obj
$(CC) obj:ztrees.obj
$(CC)
obj :Zunzip.obj ' ! PGP
: src:zfile_io.c
$(ZIPH)
: src:zglobals.c
$(ZIPH)
$(DFLAGS) $(ZFLAGS) $(mms$source) $(ZFLAGS)
: src:zinflate.c
$(mms$source) $(ZIPH)
$(DFLAGS) $(ZFLAGS) $(mms$source)
: src:zip.c
$(CC)
$(CC)
$(ZIPH)
$(DFLAGS)
obj:zinflate.obj
obj:Zip.obj
: src:zdeflate.c
$(DFLAGS) $(ZFLAGS) $(mms$source)
$(DFLAGS)
$(ZIPH)
$(ZFLAGS)
: src:zipup.c
$(DFLAGS)
$(mms$source)
$(ZIPH)
$(ZFLAGS)
$(mms$source)
: src:ztrees.c
$(ZIPH)
: srcizunzip.c
$(ZIPH)
$(DFLAGS) $(ZFLAGS) $(mms$source) $(DFLAGS)
$(ZFLAGS)
$(nms$source)
Stuff
|
obj:armor.obj : src:armor.c src:armor.h obj:charset.obj : src:charset.c src:usuals.h src:language.h src:charset.h src:system.h obj:config.obj : src:config.c src:usuals.h src:pgp.h obj:CRYPTO.obj : src:mpilib.h src:mpiio.h src:random.h src:crypto.h src: keymgmt .h src:mdfile.h src:md5.h srce:fileio.h src:pgp.h srce:rsaglue.h sre:platform.h sre:usuals.h — src:CRYPTO.C
-
!
File:
‘descrip.mms’
23
obj:idea.obj : src:idea.h src:pgp.h src:idea.c obj:FILEIO.obj : src:FILEIO.C src:random.h src:mpilib.h src:platform.h src:usuals.h src:fileio.h src:pgp.h obj: getopt.obj : src: getopt.c
src: Mpr10 shi=
obj:genprime.obj
: src:genprime.c src:genprime.h src:mpilib.h src:random.h src:platform.h src:usuals.h obj: keyadd.obj : src:mpilib.h src:random.h sre:crypto.h src:fileio.h src:keymgmt.h src:keyadd.h src: genprime.h src:rsagen.h src:mpiio.h src:platform.h src:usuals.h src:pgp-h src:language.h src:charset.h src:keyadd.c
-
-
obj: keymaint.obj : src:mpilib.h src:random.h src:crypto.h src:fileio.h src: keymgmt.h src:keyadd.h src:genprime.h src:mpiio.h src:pgp.h src:platform.h src:usuals.h src: language.h — src:charset.h src: ovmaine c obj: KEYMGMT.obj : src:mpilib.h src:usuals.h src:random.h src:crypto.h src:fileio.h src:mpiio.h srce:pgp.h srce:charset.h src:platform.h src:usuals.h src:KEYMGMT.C obj:MD5.obj : src:md5.h srce:md5.C obj:MDFILE.obj : src:mpilib.h src:mdfile.h src:md5.h src:pgp.h src:platform.h src:usuals.h src:MDFILE.C obj:MORE.obj : src:MORE.C src:mpilib.h src:pgp.h obj:MPIIO.obj ; sre:MPIIO.C sre:mpiio.h sre:mpilib.h — src:platform.h src:usuals.h obj:MPILIB.obj : src:MPILIB.C src:mpilib.h src:platform.h src:usuals.h obj:passwd.obj : src:passwd.c src:random.h src:md5.h src:pgp.h obj: PGP.obj :) src:mpilib.h src:random.h src:crypto.h sre;fileio.h src:keymgmt.h src: keymaint.h src:charset.h src:pgp.h src:config.h src:platform.h src:usuals.h — srce:PGP.C obj:RANDOM.obj : src:random.h src:pgp.h src:RANDOM.C obj:rsagen.obj : src:rsagen.c src:mpilib.h src:genprime.h src:rsagen.h — src:platform.h src:usuals.h — src:random.h src:rsaglue.h obj:rsaglue.obj : src:rsaglue.c src:mpilib.h src:mpiio.h src:pgp.h src:rsaglue.h obj:rsatst.obj : src:rsatst.c src:mpilib.h src:mpiio.h src:genprime.h — src:platform.h src:usuals.h src:rsagen.h src:random.h obj:language.obj : src:language.c src:charset.h src:usuals.h srce:fileio.h src:pgp.h obj:SYSTEM.obj : src:exitpgp.h src:system.h src:pgp.h src:mpilib.h src:mpiio.h src:fileio.h src:charset.h src:platform.h src:usuals.h src: SYSTEM.C obj:vax.obj : src:vax.mar
RSATST '
Is the
RSA/Multiple
Precision
Library
Test
Harness
obj:rsatst.exe : src:rsatst.opt obj:rsatst.obj obj:mpilib.obj obj:genprime.obj obj:rsagen.obj obj:mpiio.obj obj:random.obj obj:vax.obj obj:system.obj obj: language.obj obj:fileio.obj
$(LINK)
$(LINKFLAGS)
-
rsatst/opt
!
! Link PGP ' OBJ1 = obj:pgp.obj obj:config.obj obj:crypto.obj obj: keymgmt.obj obj:keyadd.obj obj: keymaint.obj obj:fileio.obj obj:mdfile.obj obj:more.obj obj:armor.obj obj:mpilib.obj obj:mpiio.obj obj:getopt.obj obj:genprime.obj obj:rsagen.obj obj:random.obj obj:idea.obj obj:passwd.obj obj:md5.obj obj:system.obj obj: language.obj obj:vax.obj obj:charset.obj obj:rsaglue.obj
obj:pgp.exe
: src:pgp.opt
$(RSAOBJS)
$(OBJ1)
$(ZIPOBJS)
-
$(LINK) $(LINKFLAGS) src:pgp/opt, $(RSAOBJS) $(CCLIB) src:VAXCRTL/opt
#
File:
‘pgp.def’
# File: #
25
‘pgp.def’
(New File)
NAME PGP WINDOWCOMPAT STACKSIZE 0x50000
NEWFILES
#
26
# File: #
‘pgp.mak’
(New File)
. AUTODEPEND #
*Translator
Definitions*
CC = bcc +PGP.CFG TASM = TASM
TLINK
= tlink
# 7cAObae
*Implicit
Rules*
$(CC) -c {$< } .cpp.obj:
$(CC) -c {$< }
#
*xList
EXE_dependencies charset.obj \
config.obj \ crypto.obj \ fileio.obj \ genprime.obj \ getopt.obj \ idea.obj \ keyadd.obj \ keymaint.obj \ keymgmt.obj \ language.obj \
md5.obj \
mdfile.obj
\
more.obj \ mpiio.obj \ mpilib.obj \ passwd.obj \ armor.obj
pgp.obj \
\
random.obj
\
rsagen.obj
\
system.obj \ zbits.obj \ zdeflate.obj zZfile_io.obj zglobals.obj zinflate.obj
\ \ \ \
=
\
Macros*
#
File:
‘pgp.mak’
Zip .Ob js\ Zipup.obj \ ztrees.obj \ zunzip.obj \
8086.obj \
zmatch.obj #
*Explicit
pgp.exe:
pgp.cfg
Rules*
$(EXE_dependencies)
$(TLINK) /x/c/P-/L\BCC\LIB 0&& |
cOl.obj+ charset .obj+ config.obj+ crypto.obj+ fileio.objt+ genprime.obj+ getopt.objt idea.obj+ keyadd.obj+ keymaint.obj+ keymgmt .obj+ language.objt+ md5.obj+ mdfile.objt+ more.objt+ mpiio.objt+ mpilib.objt passwd.obj+ armor .obj+
pgp.obj+
random.obj+ rsagen.objt system.obj+ zbits.objt+ zdeflate.obj+ zfile_io.obj+ zglobals.objt zinflate.objt+ zip.obj+ zipup.obj+ ztrees.objt zunzip.objt 8086.obj+ zmatch.obj
P&P
# no
map file
Gil. Akio)
| #
*Individual
File
Dependencies*
#
28
charset.obj:
charset.c
config.obj:
config.c
crypto.obj:
crypto.c
Tileio-obj:
fileio.c
genprime.obj:
getopt.obj: idea.obj:
genprime.c
getopt.c idea.c
keyadd.obj:
keyadd.c
keymaint.obj:
keymaint.c
keymgmt .obj:
keymgmt.c
language.obj: md5.obj:
language.c
md5.c
mdfile.obj:
more.obj: mpiio.obj:
mdfile.c
more.c mpiio.c
mpilib.obj:
mpilib.c
passwd.obj:
passwd.c
armor.obj:
armor.c
pgp.obj: pgp.c random.obj:
random.c
rsagen.obj:
rsagen.c
system.obj:
system.c
ZDAtS
Obs
Zba tS). C
zdeflate.obj:
zdeflate.c
répeLihe) Sho) Oley]
PAreslaley Sie) te
zglobals.obj:
zglobals.c
#
File:
‘pgp.mak’
zinflate.obj: Zip.Obye
29
zinflate.c
Zipsc
zipup.obj:
zipup.c
ztrees.obj:
ztrees.c
zunzip.obj:
zunzip.c
8086.o0bj}: 8086.asm $(TASM) /MX /ZI
/O 8086.ASM,8086.0BJ
zmatch.obj: zmatch.asm $(TASM) /DDYN_ALLOC=1
£
*Compiler
pgp.cfg:
/DSS_NEQ_DS=1
Configuration
pgp-mak
copy &&|
-ml1 -f-
=G =G -Z =i -wamb —wamp -wasm —wpro -wdef -wnod -wstv
-wuse -I\BCC\ INCLUDE
-L\BCC\LIB
—DMSDOS ; DYN_ALLOC ; SMALL_MEM =P=3¢
/MX /ZI /O ZMATCH.ASM,ZMATCH.OBJ
File*
#
30
lee
ape pops.
! nsi(NewiF ile) '! PGP.OPT - Options file for PGP/VMS \ (c) Copyright 1991-93 by Hugh Kennedy.
All
rights
reserved.
i}
'! The author assumes no liability for damages resulting from the use ! of this software, even if the damage results from defects in this ' software. No warranty is expressed or implied. '
!\ The
above
notwithstanding,
a license
'! to anyone either in the original ! this notice is not removed.
to
use
or modified
this
form
software
on
is
granted
condition
that
!
!! Version: \ !' Original:
2
OOA
13-Nov-1992
Author:
Hugh A.J.
Kennedy
O2A
11-Feb-1993
Author:
Hugh A.J.
Kennedy.
Hugh A.J.
Kennedy.
!
!iJ Modification: '
!' Update version number. Remove MD5 ' !i} Modification: 02e 14-May-1993
logical. Author:
i}
! Update version ' NAME=PGP IDENT="V2.3" ! '
number.
Add rsa
glue
stuff.
obj :more,fileio,md5 ,mdfile,getopt,system,mpilib,mpiio,random,crypto,rsagen,idea, passwd, genprime, pgp, config,vax, language, charset, armor i]
| RSA Stuff '
obj :rsaglue '
| Key Stuff !
obj :keymgmt ,keymaint ,keyadd ' ! ZIP Stuff ' obj:zbits,zdeflate,zglobals,zinflate,zip,zipup,zfile_io,ztrees,zunzip
#
File:
‘pgppwb.mak’
# File: #
on
‘pgppwb.mak’
(New File)
ORIGIN = PWB ORIGIN_VER = 2.1.49 PROJ = PGP PROJFILE = PGPPWB.MAK DEBUG = 0 BSCMAKE
=
SBRPACK
=
bscmake
sbrpack
NMAKEBSC1 NMAKEBSC2 CC = cl CFLAGS_G CFLAGS_D CFLAGS_R CXYX = Ver CXXFLAGS_G CXXFLAGS_D CXXFLAGS_R ASM = ml AFLAGS_G AFLAGS_D
= set = nmake
= /Zi
AFLAGS_R
= /nologo
MAPFILE_D MAPFILE_R LFLAGS_G LFLAGS_D LFLAGS_R
= NUL = NUL = /NOI /STACK:12288 = /CO /FAR /PACKC = /EXE /FAR /PACKC
= /AL /W2 /DDYN_ALLOC /DSMALL_MEM = /f /Od /Zi = /f- /Ot /01 /Og /Oe /Oi /Gs
/DMSDOS
/BATCH
/FR$*.sbr
/Gt
= /W2 /BATCH /FR$*.sbr = /f /Zi /Od = /f- /Ot /Oi /01 /Oe /Og /Gs
= /Cp /W2 /WX /Zm /FR$*.sbr
/BATCH
/ONERROR:NOEXE
LINKER = link ILINK = ilink LRF = echo > NUL ILFLAGS = /a /e BRFLAGS = /o $(PROJ).bsc BROWSE = 1 PACK_SBRS = 1 FILES
OBJS
= 8086.ASM ARMOR.C CHARSET.C CONFIG.C CRYPTO.C CRYPTO.H FILEIO.C\ FILEIO.H GENPRIME.C GENPRIME.H GETOPT.C IDEA.C IDEA.H KEYADD.C\ KEYMAINT.C KEYMGMT.C KEYMGMT.H LANGUAGE.C LANGUAGE.H MD5.C MD5.H\ MDFILE.C MDFILE.H MORE.C MPIIO.C MPILIB.C MPILIB.H PASSWD.C PGP.c\ PGP.H RANDOM.C RANDOM.H RSAGEN.C RSAGEN.H STDLIB.H SYSTEM.C USUALS.H\ ZBITS.C ZDEFLATE.C ZFILE_I0O.C ZGLOBALS.C ZINFLATE.C ZIP.C ZIP.H\ ZIPERR.H ZIPUP.C ZMATCH.ASM ZREVISIO.H ZTAILOR.H ZTREES.C ZUNZIP.C\ ZUNZIP.H = 8086.obj ARMOR.obj CHARSET.obj CONFIG.obj CRYPTO.obj FILEIO.obj\ GENPRIME.obj GETOPT.obj IDEA.obj KEYADD.obj KEYMAINT.obj KEYMGMT.obj\ LANGUAGE.obj MD5.obj MDFILE.obj MORE.obj MPIIO.obj MPILIB.obj\
#
32
PASSWD.obj PGP.obj RANDOM.obj RSAGEN.obj SYSTEM. obj ZBITS.obj\ ZDEFLATE.obj ZFILE_I0.obj ZGLOBALS.obj ZINFLATE.obj ZIP.obj ZIPUP.obj\ ZMATCH.obj ZTREES.obj ZUNZIP.obj = 8086.sbr ARMOR.sbr CHARSET.sbr CONFIG.sbr CRYPTO.sbr FILEIO.sbr\ GENPRIME.sbr GETOPT.sbr IDEA.sbr KEYADD.sbr KEYMAINT.sbr KEYMGMT.sbr\
SBRS
LANGUAGE.sbr MD5.sbr MDFILE.sbr MORE.sbr PASSWD.sbr PGP.sbr RANDOM.sbr RSAGEN.sbr
ZDEFLATE.sbr ZMATCH.sbr
all:
ZFILE_I0.sbr
ZTREES.sbr
ZGLOBALS.sbr
MPIIO.sbr MPILIB.sbr\ SYSTEM.sbr ZBITS.sbr\
ZINFLATE.sbr
ZIP.sbr
ZIPUP.sbr\
ZUNZIP.sbr
$(PROJ).exe
. SUFFIXES : . SUFFIXES: SSUIMSID GSS sOly)
sek
aS
oeIRIN
8086.obj : 8086.ASM 'IF $(DEBUG) $(ASM) /c $(AFLAGS_G) \ELSE $(ASM) /c $(AFLAGS_G) (‘ENDIF 8086.sbr : 8086.ASM !'IF $(DEBUG) $(ASM) /Zs $(AFLAGS_G) \ELSE $(ASM) /Zs $(AFLAGS_G) (‘ENDIF
$(AFLAGS_D)
/Fo8086.obj
8086.ASM
$(AFLAGS_R)
/Fo8086.obj
8086.ASM
$(AFLAGS_D)
/FR8086.sbr
8086.ASM
$(AFLAGS_R)
/FR8086.sbr
8086.ASM
ARMOR.obj : ARMOR.C MPILIB.H FILEIO.H mpiio.h LANGUAGE.H !IF $(DEBUG) @$(CC) /c $(CFLAGS_G)
$(CFLAGS_D)
PGP.H USUALS.H
@16-bit temporaries #define low16(x) ((x) & OxFFFF) typedef unsigned int uinti6; /* at LEAST
*/
16 bits,
maybe more
*/
#else
#define
lowi6(x)
typedef #endif
wordi6é
#ifdef /*
(x) /* this
is only ever
applied to uinti6’s
_GNUC_
__const__
* which
simply
is useful
means
info
there
are
for the gcc
no
side
effects
for
this
optimizer
*/ #define #telse #define #Hendif
CONST
__const__
CONST
/*
* Multiplication,
modulo
(2**16)+1
* Note that this code is structured on the assumption that * untaken branches are cheaper than taken branches, and the * compiler doesn’t schedule branches.
+/
/*
mul */
#ifdef SMALL_CACHE CONST static uint16 mul (register uinti6
a, register
i register
p =
word32
(word32)
p;
a *b;
lun)
vl
b = lowi6
(p);
Gl Si jo) 22> alee return (b - a) + (b < a); else
*/
uinti16;
if
(a)
uinti6
b)
function,
*/
/*
Fado
o idea.c2
*/
/*
{ return
ie —
ra?
ect
le—" bi
else
{ } } /* mul */ #endif
/* SMALL_CACHE
*/
/*
* Compute the multiplicative inverse of x, modulo 65537, using Euclid’s * algorithm. It is unrolled twice to avoid swapping the registers each * iteration, and some subtracts of t have been changed to adds.
*/ /*
mulinv */ CONST
static
mulInv
uinti6
(uintié6
WinG1 uinti6
x)
OmcO mois q, y;
sig? (Ge = 2, this fits y = 0x10001L % x;
if (y == v=
16 bits
1)
return Ol do
into
low16
(1 - t1);
des
{
fc as
5 ee
tol Ra i
tO t= q * t1; Hee uve SS Aly) return
t0;
Go = Visa x; y =.Y 4x; t1
+=
-q * t0;
} while (y != 1); return lowi6 (1 - t1); } /* mukInv */ /* * Expand
*/
a 128-bit
user
key to a working
encryption
key EK
*/
371
*/
/*
S20
ey
/*
PGP
Source
Code
and
Internals
/*
ideaExpandKey */ static
void
ideaExpandKey au shake
(byte const
*userkey,
wordi6
* EK)
oh, ops
fors¢j] = 0.) eos jtt) { EK[j] = (userkey[0] 7;
Is } /* ideaExpandKey */ /* * Compute IDEA decryption key DK from an expanded * Note that the input and output may be the same. * inverted
7,
into
an
internal
buffer,
and
then
IDEA encryption key EK Thus, the key is
copied
to
/*
ideaInvertKey */ static
void
ideaInvertKey
(word16
const
*EK,
word16
{ int
i;
Wane)
wil,
WA,
weir
word16 temp[IDEAKEYLEN] ; wordi6
*#p = temp
t1
= mulInv
t3
=
+ IDEAKEYLEN;
(+*EK++);
t2 = -*EK++; —*EK++;
*--p = mulInv (19)
=
a=) cto)
= oA SS “upabs
(*EK++);
1328
for (i = 0; “
i < IDEAROUNDS
ti = *EK++;
-
1; i++)
DK[IDEAKEYLEN])
the
output.
+7,
fe
SPATS
O Taaaverm”
*-—p
=
=*/
*EK++;
AS Syo) =
wel
ti
= muliInv
t2
=
t3
(+*EK++);
= -*EK++;
-*EK++;
*--p = mulInv jo) =
/*
(*EK++);
= 745
S8) =
9)
t3;
=
cae
Me ti
= *EK++; +> pe =) ERE £3)
=
tl:
ti = muliInv
t2 = -*EK++;
(*EK++)
t3 = -*EK++; *--p = muliInv
che)
(*EK++);
ts:
ASS
=
+—peo
B45
Gl
/* Copy and destroy temp copy */ memcpy (DK, temp, sizeof (temp)); burn
(temp);
} /* ideaInvertKey
*/
/*
* MUL(x,y) *
t16
and
computes t32.
x
x = x*y,
is modified,
modulo and
0x10001. must
be
Requires
* y may be anything, but unlike x, must be strictly * even if lowi6() is #defined. * All of these are equivalent - see which is faster
less
#ifdef SMALL_CACHE #define MUL(x,y) (x = mul(lowi6(x),y)) #else /* !SMALL_CACHE */ #ifdef AVOID_JUMPS #define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1),
(word32)x*t16
+ x + t16, x = low16(t32),
£168=!¢82>516, x! = "(x-t16)*+ (xiv; memcpy (context->oldcipher, ideaCipher (bufptr, bufptr, context->bufleft
=
8 -
bufptr, 8); context->key);
count;
do
{ t = *bufptr; *dest++ = t ~
(*bufptr++
= *srctt);
const
*src,
and
Internals
*/
/*
File:
while
‘idea.c’
*/
(--count);
BECCA
/* * * * *
*/
/*
AICS
CCGG
COCA
IAAI
I Fk i
/
Cryptographically strong pseudo-random-number generator. The design is from Appendix C of ANSI X9.17,: "Financial Institution Key Management (Wholesale)", with IDEA substituted for the DES.
/* * Initialize a cryptographic random-number * key and seed should be arbitrary. */
oe
generator.
ni
void
ideaRandInit (struct IdeaRandContext byte const seed[8]) omg
*context,
byte
const
key[16],
EL6
ideaExpandKey
(key,
context-—>bufleft
memcpy
/* * Read
=
context->key); 0;
(context->internalbuf,
out
the
RNG’s
seed,
8);
state.
*/ void
ideaRandState An
(struct
IdeaRandContext
*context,
byte key[16],
byte
seed[8] )
Gael:
memcpy
(seed,
context->internalbuf,
8);
foraviess 07 3, < S54it*) key[2 * i] = context->key[i] >> 8; key([2 * i + 1] = context->key[il ;
iy
} /*
* Encrypt
the
RNG’s
state
with
the
given
CFB
encryptor.
*/ void ideaRandWash
(struct
IdeaRandContext
byte keyseed[16 + 8];
*context,
struct
IdeaCfbContext
*cfb)
381
*/
/*
T3832
sean.
*7
:
/*
PGP Source
Code
and Internals
SL9
ideaRandState (context, keyseed, keyseed + 16); ideaCfbEncrypt (cfb, keyseed, keyseed, 16 + 8); ideaRandInit (context, keyseed, keyseed + 16);
memset
(keyseed,
0, 16 + 8);
} /* * Cryptographic * session keys.
pseudo-random-number
generator,
used
for
+/
byte
ideaRandByte
(struct
IdeaRandContext
*c)
‘A sla
if
545
('c->bufleft)
{
byte timestamp[8] ; /* Get
some
true-random
randPoolGetBytes
/* Compute axepe
next
noise
(timestamp,
8 bytes
(Ca = (08 Sh outbuf, c->outbuf, /* Compute new seed vector */ siepe ((G =) @)x Si internalbuf [i] = c->outbuf[i] burn
(c->internalbuf,
(timestamp) ;
c->bufleft
=
8;
Ip return
c->outbuf [--c->bufleft];
Me /* end
of
idea.c
*/
*/
Sigise))
c->outbuf [i] = c->internalbuf[i]
ideaCipher
(timestamp) );
c->key);
~ timestamp[il]; c->internalbuf,
c->key);
generating
/*
File:
‘keyadd.h’
/* File:
‘keyadd.h’
/* (New File) */ /* Adds int
*/
(prepends)
addto_keyring
(x
*/
| key file to key ring file (char
*keyfile,
char
*/
*ringfile);
#333
+*/
384
/*
*/
/* File: /* (New File)
/*
‘keyadd.c’
PGP
Source
PGP:
and
Internals
*/
*/
keyadd.c - Keyring merging routines for PGP. Pretty Good(tm) Privacy - public key cryptography
/*
Code
for the masses.
(c) Copyright 1990-1994 by Philip Zimmermann. All rights reserved. The author assumes no liability for damages resulting from the use of this software, even if the damage results from defects in this software. No warranty is expressed or implied. Note that while most PGP source modules bear Philip Zimmermann’s copyright notice, many of them have been revised or entirely written by contributors who frequently failed to put their names in their code. Code that has been incorporated into PGP from other authors was either originally published in the public domain or is used with permission from the various authors. PGP is available for free to the public under certain restrictions. See the PGP User’s Guide (included in the release package) for important information about licensing, patent restrictions on certain algorithms, trademarks, copyrights, and export controls.
#7 #include #include #ifdef UNIX
#include
#endif #include #include #include #include #include #include #include #include #include #include #include #include
"mpilib.h" "crypto.h" "fileio.h" "keymgmt.h" "charset.h"' "mpiio.h" "language.h" "pgp.h" “exitpgp.h" "keyadd.h" "keymaint.h"
void
gpk_close
int gpk_open
(void);
(char *keyfile);
int get_publickey (long *file_position, byte * keyID, byte * timestamp, byte
* userid,
unitptr
static
int ask_to_sign
static
boolean
n,
unitptr
(byte * keyID,
ask_first;
int
*pktlen,
e);
char *ringfile);
*/
/*
File:
‘keyadd.c’
*/
static
boolean
publickey;
/* if TRUE,
static
static
int newkeys, newsigs, newids, byte mykeyID [KEYFRAGSIZE] ;
static
struct
sig_list
struct sig list long pos;
*next;
*siglist; /*
sig
lis teadda
*/ static
void
sig_list_add
(long pos)
{ struct
sig_list
p = xmalloc
*p;
(sizeof *p);
p->pos = pos; p->next = siglist; Siglist = p; /*
So Cia ste iviid */ hy static
int
sig_list_find ai struct
(long pos)
sig_list
*p;
for (p = siglist; p; p = p->next) if (p->pos == pos) return return 0;
1;
/*
sigulastmcilear */ ip static
void
sig_list_clear 1. struct
(void)
sig_list
for (p ="siglist; { n = p->next;
free
(p);
} siglist
=
NULL;
*p,
*n;
p; p = 2)
/* add trust newrvks;
packets
*/
385
*/
/*
386
*/
/* Merge
:
signatures
* userid
from
from userid
fring
(which
/*
in fkey
PGP Source
(which is keyfile)
is ringfile)
at ringpos,
Code
and Internals
at keypos
appending
result
with to out.
*/ /*
mergesigs +/ static int mergesigs (FILE
* fkey,
char *ringfile,
char
*keyfile,
long *pringpos,
long keypos,
FILE
* fring,
FILE * out)
long ringuseridpos, ringpos; int ringpktlen, keypktlen; int
status;
byte ctb; int copying; word32 rstamp,
kstamp,
xstamp;
byte keyID[KEYFRAGSIZE] ; char
userid[256];
/* First,
copy
the
userid
ringuseridpos
= ringpos
fseek
ringpos,
(fring,
(void)
NULL,
readkeypacket
NULL,
NULL,
PascalToC
packet
plus
any
comments
or
ctrls
NULL,
NULL,
SEEK_SET) ; (fring,
NULL,
itself,
= *pringpos;
NULL,
FALSE,
&ctb,
NULL,
userid,
NULL);
(userid);
ringpktlen = ftell (fring) - ringpos; copyfilepos (fring, out, ringpktlen, ringpos) ;
for (;;) A
ringpos status
= ftell
(fring);
= nextkeypacket
Tf (status
= 0)
4. fring,
if ((status ringfile,
return
= TRUE)
userid_pos,
status;
= FALSE;
copying
= TRUE;
else
t he {
if (copying) /* Copy
ringfile
copyfilepos
}
userid
(fring,
and
out,
sigs
to out
ringpktlen,
*/
ringpos) ;
} /* End of loop for each key in ringfile fseek
(fring,
*pringpos return
ringpos,
= ringpos;
0;
} /* mergekeys
*/
SEEK_SET);
*/
userid,
= mergesigs (fkey, keyfile, &ringpos, out)) < 0)
copying
userid
+*/
/* Grab the keyID here readkeypacket
the
*/
NULL,
NULL,
393
*/
394
/*
*/
;
/*
PGP Source
Code
and Internals
/*
SIA
ISSN
ae
*
/* Adds
(prepends)
int _addto_keyring
key file to key ring file.
(char
*keyfile,
char
*/
+ringfile)
J FILEG+t oe *g, +h; long file_position,
fp;
int pktlen; byte ctb; int
status;
unit
n[MAX_UNIT_PRECISION] , e[MAX_UNIT_PRECISION] ;
unit ni[MAX_UNIT_PRECISION] ; byte keyID[KEYFRAGSIZE];
byte userid[256]; /* key certificate byte useridi[256]; word32
*/
tstamp;
byte *timestamp boolean
= (byte *) & tstamp;
userid_seen
=
int commonkeys = 0; int copying; struct newkey *nkey, char
userid
/* key certificate
timestamp
*/
FALSE;
*nkeys
= NULL;
*scratchf;
/* open
file
f for
if ((f = fopen
read,
in binary
(not
(keyfile,
FOPRBIN))
== NULL)
text)
mode...
*/
{
fprintf reGyeiban
(pgpout,
LANG
("\n\007Can’t
open key file
’%s’\n"),
keyfile);
als
} ctb
=
0;
ife(iread
(£ctb,
1,
1, £4)
=
1°)
tis key_ctb) (eth))
{ fclosouciys return
} rewind
-1;
(f);
setoutdir (ringfile); scratchf = tempfile (0); /* * get_userids
* keyring
from
both
if ringfile
*
setkrent
(ringfile) ;
setkrent
(keyfile);
init_userhash
();
files,
is not
maybe
the
should
default
also
ring.
use
the
default
public
*/
/*
File:
‘keyadd.c’
if (!file_exists
¥*/
/*
(ringfile))
{
’
/* ringfile does not exist. Can it be created? */ /* open file g for writing, in binary (not text) mode... g = fopen (ringfile, FOPWBIN); if (g == NULL) fprintf (pgpout, LANG ("\nKey ring file ringfile) ; fclose goto
’%s’
cannot be created. \n"),
(f);
err;
fclose
(g);
/* Create working output file */ /* open file g for writing, in binary if
((g = fopen
(scratchf,
FOPWBIN))
(not text)
==
mode...
*/
NULL)
{ tcloseu(t); goto
err;
newkeys
= newsigs
/* Pass /* Also
1 - copy all keys from f which aren’t in ring file copy userid and signature packets. */ (pgpout, LANG ("\nLooking for new keys...\n")); = FALSE;
fprintf
copying if (gpk_open
= newids
(ringfile)
= newrvks
= 0;
< 0)
{ fclose fclose goto
(f); (g);
/* close
key file
*/
err;
for (;;) {
file_position
= ftell
(f);
status = readkeypacket (f, FALSE, &ctb, timestamp, (char *) userid, n, e, NULL, NULL, NULL, NULL, NULL, NULL); /* Note that readkeypacket has called set_precision if (status == -1) /* EOF */ break;
if
= 0 && !filter_mode && !batchmode) for (nkey = nkeys; nkey; nkey = nkey->next) if (ask_to_sign (nkey->keyID, scratchf) != 0) break;
if (status && verbose) fprintf (pgpout, "addto_keyring: free_newkeys
(nkeys);
savetempbak
(scratchf,
return
0;
err: gpk_close endkrent /* make
/* normal
sure
we remove
rmtemp
(scratchf) ;
return
-1;
} /* _addto_keyring
*/
returned
%d\n",
ringfile);
return
(); /* save ();
maint_update
*/
to call any
if not
garbage
opened */
files
we may
have
created
*/
status);
7,
/*
File:
‘keyadd.c’
¥*/
/*
/*
addto_keyring */ int
‘iste
cia
(char *keyfile,
long
armorline
char
*tempf;
int
addflag
= 0;
= 0;
if (_addto_keyring return
char *ringfile)
(keyfile,
ringfile)
== 0)
0;
/* check if the keyfile to be added is armored while (is_armor_file (keyfile, armorline)) tempf
= tempfile
(TMP_TMPDIR
if (de_armor_file
i
rmtemp
(tempf);
return
—1;
| TMP_WIPE);
(keyfile,
tempf,
(tempf,
ringfile)
if (_addto_keyring addflag = 1; rmtemp
*/
&armorline))
== 0)
(tempf);
if (!addflag) “ fprintf
(pgpout,
Teturn
—1:
return
0;
LANG
("\nNo
keys found
in
’%s’.\n"),
else
4 }
} /*
ask */ static
fouesien int
ask_to_sign FILE
(byte * keyID,
char
*ringfile)
*f;
word32 timestamp; byte ctb, trust;
unit n[MAX_UNIT_PRECISION] , e[MAX_UNIT_PRECISION]; byte userid[256]; long fpos; int status;
keyfile);
401
*/
/*
402
*/
extern
/*
Source
Code
and
Internals
char my_name[] ;
if (getpublickey (byte return
return
(GPK_GIVEUP,
*) & timestamp,
ringfile,
userid,
n,
&fpos,
NULL,
keyID,
e) < 0)
-1;
if ((f = fopen fseek
PGP
(ringfile,
FOPRBIN))
== NULL)
-1;
(f, fpos,
SEEK_SET) ;
if (is_compromised fclose
(f);
return
0;
} if (nextkeypacket {
(f))
(f, &ctb)
< 0)
felosen(t)): return
-1;
} if
(ctb
!= CTB_CERT_PUBKEY)
fclose
(Ct):
return
0; /* don’t
ask to sign secret
} while (nextkeypacket (f, &ctb) == if (ctb == CTB_USERID) /* check break; TEmcCctbml—sCibe
fclose
(£);
return
-1;
key */
0 && !is_key_ctb first userid */
(ctb))
USERID)
Ited¢statuse—snead. trusteGr se tinust)))
fclose
(f);
return
status;
;
if (status
> 0 &&
!(options
fprintf (pgpout, LANG if (getyesno (’y’)) return
savetempbak
rmtemp
(fixfile);
return
status;
(fixfile,
>=
0)
changed.\n"),
status) ;
& MAINT_CHECK) )
("Update public keyring ringfile);
’%s’
(Y/n)?
"), ringfile);
*/
/*
416
*/
/*
} /* maint_check static int maintenance
PGP
Source
Code
and
Internals
*/
(char
*ringfile,
struct
newkey
const
*nkeys)
f int status; undefined_trust
= 0;
if (max_cert_depth max_cert_depth
/* None
so
far...
*/
> MAX_DEPTH)
= MAX_DEPTH;
if ((sec_fp = fopen (globalSecringName, FOPRBIN)) == NULL) fprintf (pgpout, LANG ("\nCan’t open secret key ring file
’%s’\n"),
globalSecringName) ;
setkrent (ringfile); setup_trust (); maint_init_mem
if
();
(mverbose || verbose) fprintf (pgpout, LANG ("\nPass 1: Looking
status
=
maint_read_data
for the \"ultimately-trusted\"
(ringfile,
keys...\n"));
nkeys);
if (sec_fp) 4 fclose (sec_fp); sec_fp
=
NULL;
a if if
(status < 0) goto failed; (mverbose
fprintf If) ((status goto
|| verbose)
(pgpout,
LANG
("\nPass
= marntetraceschain
2: Tracing ()))
uid_next else id
= allocn
= pk->pk_userids
= allocn
(sizeof (sizeof
(struct
userid));
(struct
userid));
419
*/
420
/*
if
¥*/
/*
PGP
Source
Code
and
Internals
(mverbose) id->uid_userid
keyctrl
&=
=
store_str
(userid);
~KC_LEGIT_MASK;
if (buckstop) keyctrl
|= KC_LEGIT_COMPLETE;
else
keyctrl
|= KC_LEGIT_UNKNOWN;
id->uid_next
=
NULL;
id->uid_key = pk; id->uid_legit = keyctrl; id->uid_signatures = sig = NULL; break;
case
CTB_SKE_TYPE:
ify Ghpk, |
lesbid)
break;
if (sig) sig =
sig->sig_next
= allocn
(sizeof
(struct
signature) );
else
sig = id->uid_signatures
= allocn
(sizeof
(struct
signature)) ;
sig->sig_next = NULL; sig->sig_uid = id;
sig->sig_from = getpubkey (sigkeyID); sig->sig_nextfrom = sig->sig_from->pk_signed; sig->sig_from->pk_signed = sig; sig->sig_trust = keyctrl & KC_SIG_CHECKED; break;
/* switch ctb_type keypos = ftell if
*/ (f);
(buckstopcount == 0 && mverbose) fprintf (pgpout, LANG ("No ultimately-trusted
fclose return
keys.\n"));
(£); 0;
I /* maint_read_data
*/
/*
* scan * *
/
on
keyring
for buckstop
keys
and
start
them
/*
ee *
st atic
int
maint_trace_chain
(void)
al char
*userid;
struct
pubkey
*pk;
for (pk = pklist; al
pk; pk = pk->pk_next)
the
recursive
trace_sig_chain()
#/
/*
File:
‘keymaint.c’
¥*/
if (!(pk->pk_owntrust
/*
& KC_BUCKSTOP) )
continue;
if (mverbose) fprintf (pgpout, "* Z%s\n",
LOCAL_CHARSET
if
(TRUST_LEV
(pk->pk_userids—>uid_userid));
(pk->pk_owntrust)
==
KC_OWNERTRUST_UNDEFINED )
userid = user_from_keyID (pk->pk_keyid); SET_TRUST (&pk->pk_owntrust, ask_owntrust
I trace_sig_chain return
(pk,
(userid,
pk->pk_owntrust));
0);
0;
} /* maint_trace_chain
*/
/*
* Find all signatures made with the key pk. * If a trusted signature makes a key fully legit then signatures * with this key are also recursively traced on down the tree.
made
*
* depth is the * and to check
level if we
of recursion, it is used to indent the userIDs don’t exceed the limit "max_cert_depth"
*
* NOTE: a signature made with a key with pk_depth == max_cert_depth will * not be counted here to limit the maximum chain length, but will be * counted when the validity of a key is computed in maint_final()
*/ static
int
trace_sig_chain Inca.
trust
(struct count
=
pubkey
*pk,
int depth)
10;
int counts [MAX_DEPTH] ; struct signature *sig, *s; struct pubkey *p; struct
userid
*id;
assert (depth pk_depth && pk->pk_depth pk_depth
= depth;
/* Should we ask for trust. * it! Ask the user....
If this
key is legit,
then
go for
*/ if (TRUST_LEV (pk->pk_owntrust) = = KC_OWNERTRUST_UNDEFINED ) for?{id!=" pk->pk_userids ; id}. id = id->uid_next) { compute_legit (id); if ((id->uid_legit & KC_LEGIT_MASK) == KC_LEGIT_COMPLETE)
421
*/
/*
422
*/
:
/*
PGP Source
Code and Internals
SET_TRUST (&pk->pk_owntrust, ask_owntrust (user_from_keyID (pk->pk_keyid), pk->pk_owntrust)); break;
}
}
/* Return if I haven’t * don’t need to check
signed anyone’s keys, since I any further.. -warlord 93-04-11
*/
if (!pk->pk_signed) return
#ifdef
0;
DEBUG
if (mverbose) fprintf (pgpout, "%*sid-v %s\n", 2 * depth, depth, pk->pk_userids->uid_userid) ;
'",
#endif
/* all keys signed by pk */ for
(sig = pk->pk_signed;
sig;
sig = sig->sig_nextfrom)
/* If signature is good, copy trust /* CONTIG bit currently unused */ if
(sig->sig_trust
from
signator
*/
& KC_SIG_CHECKED)
{ SET_TRUST
(&sig->sig_trust,
sig->sig_trust
|= KC_CONTIG;
TRUST_LEV
(pk->pk_owntrust)) ;
/* CONTIG
bit
currently
unused
if (mverbose) LprintfCpgpout, "'.¥s oes \n', 82 * depth, !", LOCAL_CHARSET (sig->sig_uid->uid_userid));
5 else
af SET_TRUST
(&sig->sig_trust,
KC_SIGTRUST_UNTRUSTED) ;
sig->sig_trust &= ~KC_CONTIG; if (mverbose) fprintf (pgpout, "4*s X “~s\n",
2 * depth, "", (sig->sig_uid->uid_userid));
LOCAL_CHARSET
Hs if (TRUST_FAC
(sig->sig_trust)
== 0)
continue;
p = sig->sig_uid->uid_key; /* this if (p->pk_owntrust & KC_BUCKSTOP) continue;
/* will
be handled
from
main
key signed by pk */
loop
*/
if (p->pk_depth && p->pk_depth sig_uid->uid_signatures;
s->sig_from->pk_depth;
(d < max_cert_depth) counts[d] += TRUST_FAC
(s->sig_trust);
/* * find a combination of signatures * valid through the shortest cert.
2a
trust_count
ft
for
=
that will path.
make
the key
0;
(d = 0; d < max_cert_depth;
trust_count if
s; s = s->sig_next)
++d)
+= counts[d]; .
(trust_count
>=
complete_min)
tracessigichain
(py id + 1);
break;
}
Yi #ifdef
if
DEBUG
(mverbose) fprintf (pgpout, "%tsid-s\n", 2 * depth, depth, pk->pk_userids->uid_userid) ;
"",
#endif return
0;
} /* trace_sig_chain
*/
/* * compute validity of userid/key pair, the number of signatures * trust level of these signatures determines the validity.
*/ static void compute_legit struct int
(struct
signature
trust_count,
userid
*s; legit;
if (id->uid_key->pk_owntrust legit else
=
*id)
& KC_BUCKSTOP)
KC_LEGIT_COMPLETE;
af Croust.=counta=—
for
(s =
trust_count if legit
=
0%
id->uid_signatures;
+= TRUST_FAC
-(trust=count
==
KC_LEGIT_UNKNOWN;
s;
s = s->sig_next)
(s->sig_trust); 0)
and the
423
Bf
/*
424
*/
;
/*
PGP
Source
Code
and
Internals
else if (trust_count < marginal_min) = KC_LEGIT_UNTRUSTED ; else if (trust_count < complete_min) = KC_LEGIT_MARGINAL; else = KC_LEGIT_COMPLETE;
legit legit legit
s
id->uid_legit = (id->uid_legit } /* compute_legit */
& ~“KC_LEGIT_MASK)
| legit;
/* * check if the maintenance pass changed anything * returns O if files f and g are equal and the number of changed * trust bytes if the files are different or a negative value on error
7,
/*
maint
final
*/ static int maint_final int
(char *ringfile)
status;
FILE *£; long trust_pos = 0; char userid[256] ; byte keyID[KEYFRAGSIZE] ;
byte sigkeyID[KEYFRAGSIZE] ; byte
ctb;
byte
kc_orig,
int
changed
kc_new
=
0,
mask;
= 0;
int
skip = 0; struct pubkey struct userid
struct
if
*pk; *id = NULL;
signature
*sig = NULL;
(check_only) f = fopen (ringfile,
else f = fopen if
(f ==
{
(ringfile,
FOPRBIN); FOPRWBIWN);
NULL)
fprintf (pgpout, LANG ('\n\007Can’t return
open key ring file
’%s’\n"),
ringfile);
-1;
pk = pklist; while ((status if it (status
= readkpacket
==
—Selilesitatus!
(f,
&ctb,
userid,
keyID,
sigkeyID))
=-a—o)
break;
if
(status
< 0
|| is_ctb_type
(ctb,
CTB_CERT_SECKEY_TYPE) )
!= -1)
*/
/*
File:
‘keymaint.c’
¥*/
/*
skip = 1; continue;
if (skip) if
(is_ctb_type skip = 0;
(ctb,
CTB_CERT_PUBKEY_TYPE) )
else continue;
if (is_ctb_type (ctb, CTB_CERT_PUBKEY_TYPE) | | is_ctb_type (ctb, CTB_SKE_TYPE) || ctb == CTB_USERID) trust_pos = ftell (f); pete if (read_trust (f, &kc_orig) < 0) t status
if
=
ERR_NOTRUST;
Cisictb type
continue; /* skip else
(ctb,
compr.
CIB_SKE_TYPE) )
cert.
*/
break;
+
}
switch
(ctb_type
(ctb))
% case
CTB_CERT_PUBKEY_TYPE:
assert assert
(pk && !memcmp ('!sig && !id);
(pk->pk_keyid,
keyID,
KEYFRAGSIZE));
id = pk->pk_userids; kc_new = pk->pk_owntrust ; #ifdef DEBUG
if (mverbose) Sprintt-(pgpout,-
"9
------—
#endif pk = pk->pk_next; mask = KC_OWNERTRUST_MASK
%a\n",
pk->pk_depth);
| KC_BUCKSTOP;
break; case CTB_USERID_TYPE:
assert (id && !sig); sig = id->uid_signatures; compute_legit (id); kc_new = id->uid_legit; #ifdef DEBUG
if (mverbose) fprintf (pgpout, "%c 402x %02x » > + (kc_new != kc_orig), kc_orig, #endif id
=
mask
kc_new,
id->uid_next;
= KC_LEGIT_MASK;
s\n",
id->uid_userid);
425
#/
/*
426
*/
’
/*
PGP
Source
Code
and
break;
case
CTB_SKE_TYPE:
assert assert
(sig); (!memcmp
(sig->sig_from->pk_keyid,
sigkeyID,
KEYFRAGSIZE) );
kc_new = sig->sig_trust; #ifdef DEBUG
if (mverbose && sig->sig_from->pk_userids) fprintf (pgpout, "Ac %02x 02x 4s\n", » 2? + (kc_new != kc_orig), kc_orig,
Kc_new,
sig->sig_from->pk_userids->uid_userid)
#endif sig = sig->sig_next; mask = KC_SIGTRUST_MASK break; default: mask
}
=
| KC_CONTIG;
0;
if ((kc_new & mask)
!= (kc_orig & mask))
if (!check_only) write_trust_pos
(f,
kc_new,
trust_pos);
++changed; i fcloseu (lr if (status < -1) return
eee
/* -1
is OK,
[esig
fprintf cecheamgn
(pgpout,
"maint_final:
al?
changed;
} /* maint_final
*/
/*
maint_list */ int
maint_list { int
FILE char byte
(char *ringfile)
status;
*f; userid[256]; keyID[KEYFRAGSIZE] ;
byte sigkeyID[KEYFRAGSIZE] ; char
*/
lil-id)
} return
EOF
status;
*signator;
char tchar = 0; byte ctb, kc; int owntrust = 0; int usercount = 0;
internal
error\n") ;
;
Internals
*/
/*
File:
‘keymaint.c’
aria = fopen
fprintf LANG
+*/
(ringfile,
FOPRBIN))
== NULL)
(pgpout, ("\n\007Can’t
return
/*
open key ring file
’%s’\n"),
ringfile);
-1;
} Inite crust 1sts) setkrent (ringfile); init_userhash
fprintf ces
();
(pgpout, ((status
if (status
LANG
("
KeyID
= readkpacket
==
-3
Trust
(f,
|| status
&ctb,
Validity
userid,
keyID,
User
ID\n"));
sigkeyID))
== -2)
break;
if (status continue;
< 0)
if (is_ctb_type
is_ctb_type
(ctb,
(ctb,
CTB_CERT_PUBKEY_TYPE) ||
CTB_SKE_TYPE)
|| ctb == CTB_USERID)
{ Tt
Gneadmtais
techn &kc)
= 0 && getc if (pktlen != -1)
x
(sec_fp)
== getc
(floppy_fp));
fprintf (pgpout, LANG ('"'\n\OO7WARNING: Secret key for: \"%s\"\n\ does not match the key in the backup keyring ’%s’.\n"), LOCAL_CHARSET (userid), floppyring); fprintf (pgpout, LANG ("This is a serious condition, indicating possible keyring tampering. \n")); status
}
=
—2;
}
+ ex:
}
fseek return
(f,
savepos,
status;
SEEK_SET);
} /* check_secretkey /* * setup
tables
= 0) (f,
&ctb,
userid,
NULL,
NULL))
!= -1
(ctbe=—iGlBaUSER IED)
fprintf (pgpout, "%s\n", LOCAL_CHARSET fseek (f, filepos, SEEK_SET);
(userid) );
return;
fprintf fseek
(pgpout, (f,
"(KeyID:
filepos,
%s)\n",
keyIDstring
(keyID));
SEEK_SET);
} /* show_userid */ /*
* messages printed by show_key() */ static char *owntrust_msg[] = i uu
/* Just
_LANG
("This
don’t
user
wu /* reserved wi | /* reserved
LANG LANG -LANG
static
("This ("This ("This
say
anything
is untrusted
in this
case
to certify
*/
other
keys.\n"),
*/ */
user is generally trusted to certify other keys.\n"), user is completely trusted to certify other keys.\n"), axiomatic key is ultimately trusted to certify other keys.\n"),
char *keylegit_msg[]
=
*/
/*
File:
‘keymaint.c’
¥*/
/*
a -LANG -LANG -LANG
("This ("This ("This
key/userID key/userID key/userID
association association association
is not certified.\n"), is not certified.\n"), is marginally certified.\n"),
-LANG
("This
key/userID
association
is fully
static il
char *sigtrust_msg[] Questionable
certified.\n"),
=
_LANG
(""
_LANG _LANG uu /* uu /* _LANG
("" Questionable certification from:\n "), (""| Untrusted certification from:\n "), reserved */ reserved */ ("" Generally trusted certification from:\n
certification
from:\n
."),
_LANG _LANG
("" ("|
"), Completely trusted certification from:\n "), Axiomatically trusted certification from:\n "),
ime —*
show the key in file f at file position keypos. *what’ controls the info that will be shown: SHOW_TRUST: show trust byte info SHOW_SIGS: show signatures SHOW_HASH: show key fingerprint these
constants
can
be
or’ed
*what’ can also be SHOW_LISTFMT to get the same format no signatures or extra userids will be printed in this
*what’
can be SHOW_CHANGE,
in which
case
it will
HH HEH He HE eee call show_update();
int show_key
(FILE
* f,
long keypos,
int
what)
{ int
status,
keystatus
=
-1;
long filepos; char userid[256]; unit
n[MAX_UNIT_PRECISION] , e[MAX_UNIT_PRECISION] ;
byte
sigkeyID[KEYFRAGSIZE];
word32
byte int int
timestamp;
ctb,
keyctb
= 0, keyctrl;
userids = 0; keyids = 0;
byte savekeyID[KEYFRAGSIZE] ; boolean print_trust = FALSE;
byte hash[16] ;
take
as for case.
pgp
the keyID
-kv
and
435
*/
436
/*
*/
‘
/*
PGP
Source
Code
and
Internals
int precision = global_precision; int compromised = 0; int
disabled
filepos
=
0;
= ftell
(f);
fseek
(f,
keypos,
while
((status
= readkeypacket
SEEK_SET) ;
e,
NULL,
NULL,
==
|| status
(f, FALSE,
&ctb,
(byte *) & timestamp,
userid,
n,
{
NULL,
if
(status
-2
if
(is_key_ctb
NULL,
sigkeyID,
==
&keyctrl))
!= -1)
-3)
break;
(ctb))
{ if (keyids) break; extract_keyID (savekeyID, n); keyidstt+; if (what & SHOW_HASH) getKeyHash (hash, n, e); keyctb = ctb; keystatus = status; /* remember else
if
(ctb
==
status,
could
=
error
trust
*/
CTB_KEYCTRL)
/* trust bytes only in public keyrings */ if (keystatus >= 0 && !userids) /* key packet if (keyctrl & KC_DISABLED) disabled
be version
1;
if (what & SHOW_TRUST) print_trust
else
if
if
(userids
= TRUE;
(ctb
==
PascalToC
==
CTB_USERID)
0)
(userid);
/* for display
*/
++userids; if
(what
show_update
& SHOW_CHANGE)
(key2IDstring
(n));
break;
if if
(what
& SHOW_LISTFMT)
(is_ctb_type
(keyctb,
CTB_CERT_PUBKEY_TYPE) )
byte
*/
*/
/*
File:
‘keymaint.c’
*/
fprintf (pgpout, "pub"); else if (is_ctb_type (keyctb, fprintf (pgpout, "sec"); else fprintt.(pgpout, “??77""); if (keystatus < 0) fprintf (pgpout, "7 "); else if (compromised) fprintf (pgpout, "# "); else if (disabled) fprintt (pgpout, "—- ");
/*
CTB_CERT_SECKEY_TYPE))
else
fpeinté (pgpour, ‘”) fprintt (pepoute'4a7 isiiisaey countbits (n), key2IDstring (n), cdate (×tamp)); fprintf (pgpout, "%s\n", LOCAL_CHARSET (userid)); break; /* only print default userid */
I fprintf
(pgpout,
LOCAL_CHARSET
LANG
("\nKey
for user
ID:
%s\n"),
(userid) );
fprintf (pgpout, LANG ("%d-bit key, Key ID %s, created %s\n"), countbits (n), key2IDstring (n), cdate (×tamp)) ; if (keystatus == -4) fprintf (pgpout, LANG ("Bad key format.\n")); else if (keystatus == -6) fprintf (pgpout, LANG ("Unrecognized version. \n")); else
if
(what
& SHOW_HASH)
printKeyHash (hash, FALSE); if (compromised) fprintf (pgpout, LANG ("Key has been revoked.\n")) ; if
(disabled)
fprintf (pgpout, LANG if (print_trust fprintf (pgpout, LANG }
("Key is disabled.\n")); && *owntrust_msg[TRUST_LEV (keyctrl1)] (owntrust_msg[TRUST_LEV (keyctrl)]));
!= ’\0’)
else
£ PascalToC
(userid);
if (what != 0) fprintf (pgpout, “\n"); fprintf (pgpout, LANG LOCAL_CHARSET
("Also
known
as:
%s\n"),
(userid) );
if (print_trust) read_trust
fprintf
(f,
} /* print_trust else
&keyctrl);
(pgpout,
LANG
(keylegit_msg[keyctrl
*/
if (is_ctb_type
(ctb,
CTB_SKE_TYPE) )
& KC_LEGIT_MASK]));
437
+/
/*
438
if
*/
/*
(userids
==
compromised
if
PGP
Source
Code
and
Internals
0)
1; & SHOW_CHANGE)
(what
=
show_update
(key2IDstring
(n));
break;
if
(what
if
& SHOW_SIGS)
if (print_trust)
read_trust
fprintf
(f, &keyctrl);
(pgpout,
LANG
(sigtrust_msg[TRUST_LEV
(pgpout,
LANG
("
(keyctr1)]));
else
fprintf
show_userid
Certified
by:
"));
(f, sigkeyID);
3 o; if
(status status
==
=
-1 && userids)
0;
if (!userids { status
&&
=
!compromised
&& (what
!= SHOW_CHANGE))
-1;
fprintf (pgpout, LANG ("\nWarning: keyid 44d/%s %4s has no user countbits (n), keyIDstring (savekeyID), cdate (×tamp));
} set_precision fseek return
(f,
(precision);
filepos,
SEEK_SET) ;
status;
} /* show_key
*/
/* show_update -- this function just prints * pgpout to inform the user that an update
+/
an update happened.
message
/*
show_update */ void
show_update (char *s) { fprintf (pgpout, "Updated keyID:
Ox%s\n",
s);
/*
* stripped
down
version
of readkeypacket(),
the
output
userid
to
id!\n"),
*/
/*
File:
‘keymaint.c’
* is a null */
terminated i
¥*/
/*
string.
/*
readkpacket +7 int readkpacket
(FILE
* f, byte
byte * keyID,
* ctb,
char
*userid,
byte * sigkeyID)
int status; unit n[MAX_UNIT_PRECISION] , e[MAX_UNIT_PRECISION] ; status
= readkeypacket (f, FALSE, ctb, NULL, NULL, NULL, NULL, NULL, sigkeyID, NULL);
if
(status
userid,
n,
e,
< 0)
5! #ifdef
DEBUG
if (status fprintf (stderr,
< =1) "readkeypacket
returned
%d\n",
status);
f at file
position
#Hendif return
status;
}
if (keyID && is_key_ctb (*ctb)) extract_keyID (keyID, n); if
(userid
&&
PascalToC return
*ctb
CTB_USERID)
0;
} /* readkpacket /* * write
==
(userid);
trust
*/
byte
"keyctrl"
to file
*/ /*
write_trust_pos £7, void
write_trust_pos
(FILE * f, byte keyctrl,
long fpos;
fpos = ftell (f); fseek (f, pos, SEEK_SET);
write_trust fseek
(f,
(f, keyctrl);
fpos,
SEEK_SET);
} /* write_trust_pos /*
*/
long pos)
"pos"
439
*/
/*
440
* * * *
*/
/*
PGP
Source
read a trust byte packet from file f, the trust byte will be stored in "keyctrl". returns -1 on EOF, -3 on corrupt input, and ERR_NOTRUST if the packet was not a trust byte (this can be used to check if
* a file * The
is a keyring
current
file
(with trust
position
bytes)
is left
or a keyfile).
unchanged
in this
case.
/*
read_trust */ int read_trust
{,
Code
(FILE * f, byte
unsigned sae
* keyctrl)
char buf[3];
(Gueceyel
(eee,
return
ol, 3,
22)
TS &))
-1;
Tepe@buct LON
m=mGLBEKEVGERI)
f if (isictb
(buf [0l))
fseek (f, -3L, SEEK_CUR); return ERR_NOTRUST;
as else
return
-3;
/* bad
3
if (buf[i] return
data
*/
!= 1) /* length must be 1 */ -3;
if (keyctrl) *keyctrl = buf[2]; return
0;
} /* read_trust
*/
/**¥**#**
userid
lookup
#define
HASH_ALLOC
KK
/
(ALLOC_UNIT (char
/ sizeof(struct
static
char
*store_str
static static
VOID void
*allocbuf (int size); freebufpool ();
static
struct
hashent
{ struct
hashent
*next;
byte keyID[KEYFRAGSIZE] ; char
*userid;
ap **hashtbl
=
NULL,
*hashptr;
*str);
hashent))
and
Internals
#/
/*
File:
‘keymaint.c’
static
char
static static static
int int int
¥*/
/*
*strptr; strleft = 0; hashleft = 0 nleft = 0;
#define MAXKR 8 /* max. number static char *krnames[MAXKR] ; static
nkr
int
/* * Lookup
=
userid
*/
of keyrings
for user_from_keyID()
*/
0;
by keyID
without
using
the
in-memory
hash
table.
/*
_user_from_keyID +*/ static
char
*
_user_from_keyID
(byte * srch_keyID)
af FILE int
*f; i,
status,
found = 0;
byte keyID [KEYFRAGSIZE] ; static byte
char userid[256];
ctb;
/* search for
all keyfiles
(i = 0;
!found
if ((f = fopen continue; while
next) if (memcmp (keyID, p->keyID, KEYFRAGSIZE) == 0) return return
p->userid;
NULL;
} /* user_from_keyID /* * add
keyfile
* the
hash
to
*/
userid
hash
table,
userids
table.
*/ /*
setkrent +/ int
setkrent af mB
(char *keyring)
abe
assert
(nkr
< MAXKR);
if (keyring == NULL) keyring = globalPubringName; were (ai S Oe a & meee ersi)) if (strcmp (keyring, krnames[i])
==
return 0; /* duplicate name */ krnames[nkr++] = store_str (keyring); return
0;
} /* setkrent
*/
/*
endkrent */ void
endkrent
(void)
hashleft
hashtbl nkr
=
=
=
strleft NULL;
0;
freebufpool
();
=
0;
0)
are
added,
endkrent()
clears
*/
/*
File:
‘keymaint.c’
} /* endkrent
¥*/
/*
*/
/*
-
5
ae:
userid
hash
table,
read
all
files
set
with
setkrent()
*
/*
anit -userhash ok
int
init_userhash “
(void)
FILE *f; Ante sicabils
aes
byte keyID[KEYFRAGSIZE] ; char userid[256] ; byte ctb; int keyflag;
if (!hashtb1) ‘ hashtbl = allocbuf (PK_HASHSIZE memset (hashtbl, 0, PK_HASHSIZE foreG
—s07mie
keyID, keyID, KEYFRAGSIZE) ; hashptr->userid = store_str (userid); hashptr->next = hashtbl[PK_HASH (keyID)]; hashtb1[PK_HASH (keyID)] = hashptr; +thashptr; --hashleft;
keyflag
= 0;
} F
keyID,
if (!hashleft)
hashleft
Hs
= readkpacket
fclose ts return
0;
(f);
NULL))
!= -1)
443
#7),
/*
444
+*/
/*
} /* init_userhash /* * memory
PGP
Source
Code
and
Internals
*/
management
routines
*/ /*
maint_init_mem */ static
void
maint_init_mem
pkhash memset
(void)
= allocbuf (PK_HASHSIZE (pkhash, 0, PK_HASHSIZE
* sizeof * sizeof
(struct (struct
pubkey pubkey
*)); *));
/*
maint_release_mem */ static
void
maint_release_mem i nleft = strleft
(void)
0; =
pkhash = N LL; freebufpoo Hqo (
i; /*
* allocn() does * of ALLOC_UNIT */
the same as malloc(). Memory is allocated in chunks bytes, all memory can be freed by calling freebufpool().
/*
allocn */ static
VOID
*
allocn {
(int
size)
static
#ifndef size = #endif assert
if
char
MSDOS
*ptr;
/* don’t
align on MSDOS
(size
+ 3) & “3;
(size
< ALLOC_UNIT);
(size
> nleft)
{
ptr = allocbuf nleft
=
} nleft
ptr
+=
-=
(ALLOC_UNIT);
ALLOC_UNIT;
size; size;
to save memory
*/
*/
/*
File:
return
‘keymaint.c’
ptr -
} /* allocn
*/
/*
size;
*/
/*
i
apace
does
the
same
as
strdup(),
but
allocates
*
memory
with
allocbuf()
/*
store_str */ static
char
store_str
*
(char
‘.
int
size
if
(size
= strlen
fprintf (size
(stderr,
= allocbuf
strcpy
(strptr, += -=
str);
size;
strptr
struct
char
(ALLOC_UNIT);
size; -
} /* store_str
struct
string too long\n");
= ALLOC_UNIT;
strptr
static
"store_str:
> strleft)
strptr
strleft
+ 1;
NULL;
strleft
return
(str)
> ALLOC_UNIT)
return
If
*str)
bufpool
bufpool
buf[1];
size;
*/
*next;
/* variable
size
*/
J *bufpool long
= NULL;
totalsize
/* * allocate
* freed
= 0;
buffer,
with
one
all
call
*/ /*
allocbuf */ static
VOID
allocbuf
*
(int
size)
{ struct
bufpool
*p;
buffers
allocated
to freebufpool()
with
this
function
can
be
445
*/
/*
446
*/
/*
p = xmalloc (size + sizeof totalsize += size; p->next = bufpool; bufpool = p; return p->buf;
} /* allocbuf
(struct
bufpool
PGP
Source
Code
*));
*/
/*
* free all memory */
obtained
with
allocbuf()
/*
freebufpool */ static
void
freebufpool
(void)
“ struct
if
bufpool
*p;
(verbose) fprintf (pgpout,
totalsize
while
=
"\nMemory used:
0;
(bufpool)
3! p =
bufpool;
bufpool
free nleft
=
= bufpool->next ;
(p); strleft
} /* freebufpool
=
*/
hashleft
=
0;
%ldk\n",
totalsize
/ 1024);
and
Internals
*/
/*
File:
‘keymgmt.h’
/* File:
*/
/*
‘keymgmt.h’
447
*/
/* (New File) */ Lethe
- headers
for keymgmt.c
*
/*
Return
printable
public
key fragment.
+*/
char *keyIDstring (byte * keyID); char *key2IDstring (unitptr n); extern
char
const
blankkeyID[];
/* Do an RSA key pair generation, int
dokeygen
/* Edit
the
(char
*numstr,
userid
and/or
into the ring files
int
dokeyedit
(char
*/
and write
char
*numstr2,
pass phrase
*mcguffin,
char
for
them out to the keyring files. char
*/
*username) ;
an RSA key pair,
and put them
back
*ringfile);
/* Copy the first entry in key ring that has mcguffin string in userid and put it into keyfile */ int extract_from_keyring (char *mcguffin, char *keyfile, char *ringfile, boolean transflag);
/* Lists int
all
entries
view_keyring
boolean
in keyring that have mcguffin string
(char
*mcguffin,
show_signatures,
boolean
char
in userid
*/
*ringfile,
show_hashes);
/* Signature-check all entries in keyring that have mcguffin string in userid */ int dokeycheck (char *mcguffin, char *ringfile, int options) ;
/* options: #define #define
/* Allow int
*/
CHECK_ALL CHECK_NEW
user
0 /* Check all signatures */ 1 /* Only check new signatures
to remove
remove_sigs
(char
signatures
*mcguffin,
*/
from keys in keyring that have mcguffin
char
*ringfile);
/* Remove the first entry in key ring that has mcguffin int remove_from_keyring (byte * keyID, char *mcguffin,
char
*ringfile,
boolean
string
in userid
secring_too) ;
/* Extract key fragment from modulus n */ void extract_keyID (byteptr keyID, unitptr n);
/* Write message prefix keyID to a file void writekeyID (unitptr n, FILE * f);
*/
/* Extract public key corresponding to keyID or userid int getpublickey (int flags, char *keyfile, long *file_position, int *pktlen, byte * keyID, byte
* timestamp,
byte
* userid,
unitptr
n,
from
keyfile
*/
*/
*/
a)
/*
448
*/
unitptr
/* flags:
/*
PGP
Source
Internals
e);
GPK_SECRET
/* Extract
32 /* We are
actually
getting
*/
a secret
key */
private key corresponding to keyID or userid from keyfile
int getsecretkey (int flags, char *keyfile, byte byte * hpass, boolean * hkey, byte * userid, unitptr
and
*/
#define GPK_GIVEUP 1 #define GPK_SHOW 2 #define GPK_NORVK 4 #define GPK_DISABLED 8 /* Flag used in getsecretkey() only - should it be GSK_? /* Prevents use of existing password list. */ #define GPK_ASKPASS 16 #define
Code
n,
unitptr
e,
unitptr
d, unitptr
p,
* pe
unitptr
q,
in a keyring
*/
byte
*/
* timestamp,
unitptr wu); /* Return true int is_key_ctb
if ctb is one (byte ctb);
for
/* Read next key packet from * the file pointer to point
a key
file f, return its ctb beyond the key packet.
in *pctb,
and
advance
sal short
nextkeypacket
/* Read
the
* pointers.
next
(FILE
key
Most
* f, byte
packet
from
pointers
can
* pctb);
file
f,
be NULL
return
without
info
about
breaking
it
in
the
various
it.
*/ struct
short
IdeaCfbContext;
readkeypacket byte
(FILE
* timestamp,
* f,
char
struct
IdeaCfbContext
unitptr n, unitptr e, unitptr d, unitptr byte * sigkeyID, byte * keyctrl); /* Starting at key_position * matches C string userid. getpubuserid
long
(char
*keyfile,
*userid_position,
byte
p,
unitptr
q, unitptr
int
long key_position,
*userid_len,
boolean
byte
void getKeyHash (byte * hash, unitptr n, unitptr e); void printKeyHash (byteptr hash, boolean indent);
int
int
is_compromised
disable_key
(char
*,
(FILE * f); char
*);
u, which
* userid,
exact_match);
int getpubusersig (char *keyfile, long user_position, byte byte * timestamp, long *sig_position, int *sig_len);
extern
* pctb,
in keyfile, scan for the userid packet Return the packet position and size.
a7,
int
*cfb,
*userid,
* sigkeyID,
*/
/*
File:
‘keymgmt.c’
/* File:
¥*/
/*
‘keymgmt.c’
*/
/* (New File) */ /*
keymgmt.c - Key management routines for PGP. Pretty Good(tm) Privacy - public key cryptography
PGP:
(c) The of
for the
masses.
Copyright 1990-1994 by Philip Zimmermann. All rights reserved. author assumes no liability for damages resulting from the use this
software,
software.
even
No warranty
if
the
damage
is expressed
results
or
from
defects
in this
implied.
Note that while most PGP source modules bear Philip Zimmermann’s copyright notice, many of them have been revised or entirely written by contributors who frequently failed to put their names in their code. Code that has been incorporated into PGP from other authors Was either originally published in the public domain or is used with permission from the various authors. PGP
is available
for
See the PGP User’s important certain
free
Guide
information
algorithms,
to the
public
(included
about
licensing,
trademarks,
under
certain
in the release patent
copyrights,
restrictions.
package)
restrictions
and
export
for on
controls.
#7 #include #include #ifdef UNIX
#include
#endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include
"system.h" "mpilib.h" "random.h" ''crypto.h" ''fileio.h" '"keymgmt.h" "rsagen.h" ''mpiio.h" "language.h" "pgp.h" ''md5.h" "'charset.h" "keymaint.h" "idea.h"
/* #* ** **
*/
Convert to or from external byte order. Note that convert_byteorder does nothing is the same as the internal byteorder.
if the
external
byteorder
449
*/
/*
450
*/
:
#define
convert2(x,lx)
#define
convert(x)
* check * * * *
/*
convert_byteorder(
convert2(
if userid matches
(x),
the
Source
(byteptr)&(x),
sizeof(x)
substring,
PGP
Code
(1x)
and Internals
)
)
magic
characters
can be used to match start and end of userid. if n is NULL, only return TRUE if substr is an exact userid, a substring does not match in this case. the comparison is always case insensitive
~ and
match
$
of
*/
/*
BASS el {Hessel *
static boolean userid_match (char
*userid,
char
*substr,
unitptr
n)
sf boolean match_end = FALSE; int id_len, sub_len, i;
char buf[256],
if (substr return
if
*p;
NULL
|| *substr
==
’\0’)
NULL
|| *userid
==
’\0’)
TRUE;
(userid return
==
sub[256],
==
FALSE;
/* Check whether we have an ASCII af Gm '= NULL && substr[0] == °02 { userid = key2IDstring (n); Hilo sige a=
or hex userID to check for && to_lower (substrfil|) ==
Ae
iP id_len = strlen (userid); for (i = 0; i =10?
*/
i1-—)
sprintf (bufptr, bufptr += 2;
"%02X",
keyID[i]);
#else
/* MSB-first for
if
keyID
format
(i = KEYFRAGSIZE
-
sprintf
"%02X",
(bufptr,
bufptr
#endif *bufptr return
=
+=
4;
*/ i < KEYFRAGSIZE;
i++)
keyID[i]);
2;
’\0’;
keyIDbuf;
} /* keyIDstring */
/*
extract_keyID
*/
void extract_keyID (byteptr keyID, unitptr n) /* * Extract key fragment from modulus n. keyID * at least KEYFRAGSIZE bytes long.
{
byte
array
must
lf
byte buf [MAX_BYTE_PRECISION SHOTt Mel;
+ 2];
£1110 (buf, KEYFRAGSIZE + 2); /* in case n is too reg2mpi (buf, n); /* MUST be at least KEYFRAGSIZE #ifdef
XLOWFIRST
i = reg2mpi
(buf,
n);
/* MUST
be
at least
KEYFRAGSIZE
/* For LSB-first keyID format, start of keyID is: i = 2; /* skip over the 2 bytes of bitcount */
for (j = 0; j < KEYFRAGSIZE;) keyID[jt++] Helse
short */ long */
= buf [i++];
*/
long
*/
be
and Internals
*/
/*
File:
‘keymgmt.c’
¥*/
/*
i = reg2mpi (buf, n); /* MUST be at least KEYFRAGSIZE /* For MSB-first keyID format, start of keyID is: */ i =
i+
2 -
KEYFRAGSIZE;
for (j = 0; j < KEYFRAGSIZE;)
long
*/
4
= buf[it++];
keyID[j++] #tendif
} /* extract_keyID
*/
/*
key2IDstring a7 char
*
key2IDstring /*
{
(unitptr n)
Derive the key abbreviation fragment from and return printable string of key ID. n is key modulus from which to extract keyID.
the modulus
n,
MAX_KEYCERT_LENGTH
&&
-
detected
*/
certificate
length */
3)
/* bad length */ = ftell
(f) + cert_length;
/* * skip packet and return, keeps us in sync when we hit a * version error or bad data. Implemented oddly to make it * only one statement. */ #define SKIP_RETURN(x) return fseek(f, next_packet, SEEK_SET), if
(ctb
==
CTB_USERID)
it
if (cert_length > 255)
*/
*/
lis_ctb_type
return
CTB
(ctb != CTB_CERT_SECKEY) != CTB_KEYCTRL) &&
!is_ctb_type
cert_length
*/
certificate
eof */
type
/* Either bad key packet or X/Ymodem TeGhatan, (eine) == OGY) 7 —al 2g Ws
if
key
x
u,
*/
/*
File:
return
‘keymgmt.c’
¥*/
/*
-3; /* Bad Monge, error ot (userid)
*/
userid[0] = cert_length; /* Save user ID length */ fread (userid + 1, 1, cert_length, f); /* read rest
of user
}
ID */
else
fseek
(f,
(long)
return
iF else 4
if
if
cert_length,
0; /* normal
(is_ctb_type
SEEK_CUR);
return
(ctb,
*/
CTB_SKE_TYPE))
(sigkeyID)
fread (&version, 1, 1, f); /* Read version of sig packet if (version_byte_error (version) ) SKIP_RETURN (-6); /* Need a later version */ /* Skip
timestamp,
fread
(&mdlen,
fseek
(f,
/* Read fread
validity
period,
and type
byte
*/
*/
1, 1, f);
(long)
mdlen,
and return
(sigkeyID,
SKIP_RETURN
SEEK_CUR);
KEY ID */
1, KEYFRAGSIZE,
(0);
/* normal
f);
return
*/
else if (ctb == CTB_KEYCTRL) f return
if (cert_length != 1) -3; /* Bad length error if (keyctr1l)
fread
(keyctrl,
1, cert_length,
*/ f);
/* Read key control
byte
*/
else
fseek
(f, (long) cert_length, SEEK_CUR); return 0; /* normal return */
a else
if
(!is_key_ctb
SKIP_RETURN
(0);
/* Here we have if
(n
/* comment
a key packet
return
or other packet
*/
*/
*/
!= NULL)
set_precision fread
(ctb))
/* normal
(Xversion,
Sete UNIT_PRECISION); 1,
1, f);
/* read
if (version_byte_error (version) ) SKIP_RETURN (-6); /* Need a later if (timestamp)
/* safest
and
check
version
opening assumption
version
*/
*/
*/
459
*/,
/*
460
+*/
fread
/*
(timestamp,
timestamp
1, SIZEOF_TIMESTAMP,
f);
Source
/* read
Code
and
Internals
certificate
*/
convert_byteorder
external
PGP
(timestamp,
SIZEOF_TIMESTAMP);
/* convert
from
form */
else
t fseek
fread
(f,
(long)
(&validity,
SIZEOF_TIMESTAMP,
1, sizeof
SEEK_CUR);
(validity),
£);
/* Read
validity
period
*/
key material...
*/
convert (validity); /* convert from external byteorder /* We don’t use validity period yet */ freads(alg,015.15
2);
if (version_error
(alg,
RSA_ALGORITHM_BYTE) )
SKIP_RETURN (-6); /* Need a later version /*** End certificate header fields ***/ /* We’re
past
cert_length
certificate
-=
(read_mpi
Ga,
if
that
(d ==
WNiIA,
(e,
-=
INE)
/* data
precision
(read_mpi
if
a2,
(-4);
SKIP_RETURN cert_length
look
*/
at
some
+ 2 + 1;
data */
(0);
SKIP_RETURN
/* Note
now
/* Skip key certificate
SKIP_RETURN if
headers,
1 + SIZEOF_TIMESTAMP
if (n == NULL)
*/
f,
(-4);
was
FALSE,
0);
("(No changes will be made.)\n"));
/* init CFB IDEA key */ if (hidekey) it }
*/
= TRUE;
fprintf (pgpout, LANG if (getyesno (’n’))
goto
string
TRUE;
ideakey);
(y/N)?
"));
/*
File:
‘keymgmt.c’
¥*/
/*
/* First write secret key data to a file */ fname = tempfile (TMP_TMPDIR | TMP_WIPE); writekeyfile (fname, useridpengsee,=d; p,q;
if (hidekey)
hidekey i);
? &cfb
: 0, timestamp,
/* done with IDEA to protect
ideaCfbDestroy
RSA secret
key */
(&cfb);
if (changeID)
x keylen’=
+1);
/* don’t
copy userid */-
else
£
f = fopen if (f == err;
goto
(fname,
FOPRBIN);
NULL)
nextkeypacket (f, &ctb); keylen = ftell (f); fclose (f);
if (merge_key_to_ringfile
a
fprintf goto
fprintf
(pgpout,
LANG
/* skip key packet
(fname,
secring,
{
(pgpout,
LANG
if (insert_userid
fprintf goto
}
pslength,
("\n\007Unable to update secret
keylen)
< 0)
key ring.\n"));
err;
("\nSecret
key ring updated...\n"));
/* Now write public key data to file if (changeID)
£
fps,
*/
(pgpout,
LANG
(ringfile,
*/
userid,
("\n\007Unable
fpp) < 0)
to update public key ring.\n"));
err;
fprintf
(pgpout,
LANG
("Public key ring updated.\n"));
fprintf
(pgpout,
LANG
("(No need to update public key ring)\n"));
else
rmtemp done:
mp_burn mp_burn mp_burn mp_burn
(fname);
(d); /* burn (p); (q); (u);
sensitive
data on stack
*/
505
*),
/*
506
*/
/*
mp_burn
(e);
mp_burn
(n);
return 0; /* normal return */ err: mp_burn (d); /* burn sensitive
mp_burn
(p);
mp_burn mp_burn
(q); (wu);
mp_burn
(e);
mp_burn
(n);
rmtemp
(fname);
return
-1;
/* error
} /* dokeyedit
return
data
on
stack
PGP
Source
Code
and
Internals
*/
*/
*/
/*
disable_key +/ int
disable_key { PILE «+f; byte
(char *keyguffin,
char
*keyfile)
keyctrl;
byte keyID[KEYFRAGSIZE] ; byte userid[256]; unit
n[MAX_UNIT_PRECISION] , e[MAX_UNIT_PRECISION];
long
fp;
int pktlen;
strcpy if
((char
*) userid,
keyguffin);
(getpublickey (GPK_SHOW NULL, userid, n, e) =
NULL,
in secring
*/
to permanently
revoke
your public key\n\
a secret key compromise certificate\n\ (y/8)7 “); LOCALLCHARSET ((chars*)) userid)).
if (getyesno (’n’)) compromise (keyID, ((f = fopen
NULL,
0)
*) userid);
fprintf (pgpout, LANG ("\nDo you want
return
&fp,
n);
(GPK_GIVEUP,
/* can only compromise
by issuing for \""/s\""
keyfile,
-1;
extract_keyID if
| GPK_DISABLED,
(keyfile,
keyfile); FOPRWBIN))
==
NULL)
NULL,
*/
/*
File:
‘keymgmt.c’
¥*/
/*
af fprintf (pgpout,: LANG ("\n\007Can’t return
fseek
(f,
open key ring file
’%s’\n"),
keyfile);
-1;
fp + pktlen,
SEEK_SET);
if (read_trust (f, &keyctrl) < 0) { fprintf (pgpout, LANG ("\n\007File ’%s’ is not a public keyring.\n"), keyfile); fprintf (pgpout, LANG ("You can only disable keys on your public keyring.\n")); fclose
(f);
Eecilin
a
Ip , if (keyctrl & KC_DISABLED) it fprintf (pgpout, LANG ("\nKey is already disabled.\n\ Do you want to enable this key again (y/N)? ")); keyctrl
&=
~KC_DISABLED ;
fprintf
(pgpout,
keyctrl
|= KC_DISABLED;
else
f,
A; if (!getyesno fclose
(£);
re(ahinjboainl
ule
write_trust_pos fclose (f); return
LANG
("\nDisable
this
key
(y/N)?
"));
(’n’))
(f, keyctrl;
fp + pktlen);
0;
} /* disable_key
*/
/#SSsstsStSssssSSSSSSSsSSSSSSsSSSSSSSSSSSSS
SS
SSS
SS
Ss
Ss
sssSsssssssssssssat/
/*
* * * *
*/
Do an RSA key pair generation, and write them out to the keyring files. numstr is a decimal string, the desired bitcount for the modulus n. numstr2 is a decimal string, the desired bitcount for the exponent e. username is the desired name for the key.
507
#/
/*
508
*/
/*
PGP
Source
Code
and Internals
/*
dokeygen
*/
int dokeygen
(char
*numstr,
char
*numstr2,
char
*username)
unit n[{MAX_UNIT_PRECISION] , e[MAX_UNIT_PRECISION] ; unit d(MAX_UNIT_PRECISION] , p[MAX_UNIT_PRECISION]; unit
q[MAX_UNIT_PRECISION] , u[MAX_UNIT_PRECISION] ;
char
*fname;
wordié6
iv[4];
/* for
IDEA
CFB
mode,
to
protect
RSA secret key */ byte userid[256]; short keybits, ebits; word32 tstamp; boolean hidekey; /* TRUE boolean cryptrandflag;
iff
secret
key
is
encrypted
*/
byte ideakey[16]; struct
if
IdeaCfbContext
(!numstr
1) 2) 3)
fputs 512 #768 1024
Choose
1,
|| strlen
2,
or
3,
or
enter
==
0)
desired
= (char *) userid;
getstring
(numstr,
keybits = 0; while ((*numstr
>=
’0’)
= keybits
if (keybits Tecurne
(numstr)
(LANG ("Pick your RSA key size:\n\ bits- Low commercial grade, fast but less secure\n\ bits- High commercial grade, medium speed, good security\n\ bits- \"Military\" grade, slow, highest security\n\
numstr
keybits
cfb;
1:
5, TRUE);
&&
number
/* echo
(*numstr
(keybits
== 0) /* user entered /* error return */
keybits
#ifndef
=
3S
null
/* High commercial
DEBUG
keybits
’0’); response
grade */
/* Military grade */
/* minimum RSA keysize: if (keybits < 384) = 384;
*/
"),
’9’))
-
grade */
3)
1024;
bits:
keyboard
2)
= 768;
if (keybits keybits
a
1024)
keybits
=
1024;
} else
if keybits
(keybits =
> 2048)
2048;
} #else
if (keybits > MAX_BIT_PRECISION) keybits = MAX_BIT_PRECISION; #endif
ebits = 0; /* number of bits in e */ while ((*numstr2 >= ’0’) && (*numstr2 0);
/* init CFB IDEA key */ if (hidekey)
{ ideaCfbInit
(&cfb,
ideakey) ;
trueRandAccumLater
(64);
/* IV for
encryption
/* As rsa_keygen does a major accumulation of random * any others for a seed file, let’s get them at the
a7
cryptrandflag = (cryptRandOpen if (cryptrandflag) trueRandAccumLater
fputs if
{
(LANG
(rsa_keygen
fputs
(LANG
return
-1;
PUtCEW \ne, if
("\nNote (n,
e,
((struct
*/ bits, if we same time.
IdeaCfbContext
*) 0) < 0);
(192);
that key generation d, p,
q, u,
("\n\007Keygen /* error
is a lengthy process.\n"),
keybits,
failed!\n"),
return
ebits)
< 0)
pgpout) ;
*/
pepoub)s
(verbose)
{ fprintf
(pgpout,
mp_display mp_display
fputs
(LANG
need
LANG
("" modulus ("exponent
("Display
("Key n e
bee
ID %4s\n"),
key2IDstring
(n));
rah) 2
rte) s
secret
components
(y/N)?"),
pgpout);
pgpout);
*/
/*
File:
‘keymgmt.c’
if (getyesno mp_display mp_display mp_display mp_display
¥*/
/*
©5641
(’n’))
("exponent (" prime (" prime (" inverse
d p q u
=", =", =", =",
d); p); q); u);
A; tstamp = get_timestamp fputc (’\007’, pgpout); fflush (pgpout);
(NULL);
/* Timestamp when key was generated
*/
/* sound the bell when done with lengthy process
*/
/* First, write out the secret key... */ fname = tempfile (TMP_TMPDIR | TMP_WIPE) ; writekeyfile
(fname,
mp_burn
(d);
mp_burn mp_burn
(p); (q);
mp_burn
(u);
hidekey
if (hidekey) /* done with ideaCfbDestroy (&cfb);
if (file_exists
: 0,
tstamp,
IDEA to protect
userid,
RSA secret
n,
e,
d,
p,
q,
u);
key */
(globalSecringName) )
merge_key_to_ringfile
rmtemp
? &cfb
(fname,
globalSecringName,
OL,
0,
-1L);
(fname);
else
savetemp /* Second, fname
(fname,
write
= tempfile
writekeyfile
out the public (TMP_TMPDIR
(fname,
if (file_exists {
globalSecringName) ;
NULL,
*/
tstamp,
userid,
(fname,
mp_burn
mp_burn
(e);
(n);
e,
NULL,
globalPubringName,
(fname) ;
else savetemp
n,
NULL,
NULL,
(globalPubringName) )
merge_key_to_ringfile
rmtemp
key...
| TMP_WIPE);
(fname,
globalPubringName) ;
OL,
0, -1L);
NULL) ;
+7
/*
512
*/
/*
fputs
(LANG
("\007Key
/* *
If
need
we
generation
a seed
file,
completed.\n"),
create
it now.
*/ if (cryptrandflag) { trueRandConsume
(192);
cryptRandInit ((struct IdeaCfbContext /* It will get saved by exitPGP */
} return
0; /* normal
} /* dokeygen */
return
*/
*) 0);
PGP
Source
pgpout);
Code
and
Internals
*/
/*
File:
/*
File:
‘language.h’
/* (New File) /* or *
*/
*/
/#
‘language.h’
*/
*/
language.h Include file
for PGP
foreign
language
translation
facility
/*
* Strings * into * LANG
with LANG()
around them are found by automatic
* is no string to be extracted */ extern
char
/* * Use
the
*LANG dummy
* shouldn’t
af
#define extern
tools
and put
the special text file to be translated into foreign languages. () (note the space between ’G’ and ’(’) should be used if there
macro
*s); _LANG
be processed
_LANG(x) char
(char
(eg. prototype).
~for
strings
by the LANG
that
function
should
be
(eg.
array
extracted,
but
initializers).
x
language[];
/* language
selector prefix for string file */
#8523
*/
/*
514
*/
/*
/* File:
‘language.c’
PGP
Source
Code
and
Internals
*/
/* (New File) */ /*
language.c - Foreign language translation for PGP Finds foreign language "subtitles" for English phrases in external foriegn language text file.
(c) Copyright
1990-1994
by Philip Zimmermann.
All rights reserved.
The author assumes no liability for damages resulting from the use of this software, even if the damage results from defects in this software. No warranty is expressed or implied. Note that while most PGP source modules bear Philip Zimmermann’s copyright notice, many of them have been revised or entirely written by contributors who frequently failed to put their names in their code. Code that has been incorporated into PGP from other authors was either originally published in the public domain or is used with permission from the various authors. PGP is available for free to the public under certain restrictions. See the PGP User’s Guide (included in the release package) for important information about licensing, patent restrictions on certain algorithms, trademarks, copyrights, and export controls.
*/ #include #include
#include #include
#include #include
"usuals.h" "fileio.h"
#include #include
"language.h" "pgp.h"'
#include #include
"'charset.h" "armor.h"
#define #define
SUBTITLES_FILE LANG_INDEXFILE
#define
STRBUFSIZE
char language[16]
"language.txt" "language.idx"
2048
= "en";
static
char
*strbuf;
static
char
lang[16];
/* The language
/* readstr
sets
this
code,
defaults
to the
to English */
language
id of
the msg it last read */ static static /*
int int
subtitles_available line = 0;
=
0;
subtitles_available is used to determine if we know whether the special subtitles_file exists. subtitles_available has the following values: O = first time thru, we don’t yet know if subtitles_file exists.
*/
/*
File:
1
‘language.c’
we we
1
have have
already already
¥*/
/*
determined determined
that that
subtitles_file subtitles_file
exists. does not
exist.
*/ #define #define #define #define #define #define #define
NEWLINE 0 COMMENT 1 INSTRING 2 ESCAPE 3 IDENT 4 DONE 5 ERROR 6 ERR1 7
/* Look
for
#define
*
If
and return
nlabort
* before
we
is
true,
find
the
a quoted return
string
failure
from if
we
the find
file. a blank
line
opening. quote.
*/ /*
readstr */
static char * readstr (FILE * f, Ante
char
*buf,
int
nlabort)
cead:
char +p = buf; int state = NEWLINE; Int.
15 =
while
0;
((c = getc
if
(c-=2
(f))
!= EOF)
?’\r")
continue;
/* line numbers are only if (line && c == ’\n’) ++line; SW
itch
(state)
af case NEWLINE: switch (c)
“0 case
UGE Ds
state = break; case
PGE
COMMENT;
26
state = INSTRING; break; Nn): case Sige (nlabort)
1 =
NOE:
return
buf;
*buf
i,
incremented
when
creating
index
file
*/
615
*/
/*
516
*/
/*
PGP
Source
error\n",
line);
default:
if
(i ==
008%
isalnum
(c)))
{ state
=
IDENT;
lang[i++]
= ¢;
break;
if
('!isspace
fprintf
(stderr,
state
ERROR;
=
(c)) "language.txt:%d:
ly HF break; case COMMENT:
if
(c ==
’\n’)
state = NEWLINE; break; case INSTRING:
switch
(c)
CASE
O\\?s
state = ESCAPE; break; caseu.: state = DONE; break; default: *pt++ = c; break; case
ESCAPE:
switch
(c)
\ aAsmCumilul "q"
(b)
) 9
Lovee,
> vad"
(x1)
7 "ad"
(xh)
“0
(xi)
JN
\
c #else
#if defined(__GNUC__) && defined(i386) && defined(MUNIT32) Hdetinerinul (a,b, x.,2n) asm mull ,2"s "=a" (x1) ."=d (xhjevo™
(a)i'g"
#else
#define
MUNITHMASK
(((unsigned
#ifdef MUNIT16 #define lmul(a,b,xl,xh)
long)1
\
{\ unsigned long XX = (unsigned long) x1 xhe=e
rxeeroxifrt: ke 16 N
\
(MULTUNITSIZE/2); Xbl = Xbb&MUNITHMASK; Xbh = Xbb>>(MULTUNITSIZE/2); \
Xx1 = Xal*Xbl;
\
LOD S MEE Gels Kx3) =" Xal+Xbh;
\ \
Xx4 = Xah*Xbh; KxB = Xx2+Xx3;
\ \
Xx4 += ((MULTUNIT) (Xx5 < Xx2)) (MULTUNITSIZE/2)); \ \ \ x1 xh
Xx6;
\
Xx4-
\
} #Hendif
#endif #Hendif
#Hendif #endif
/* PATCH_ASM
*/
\
\
+*/
/*
File:
‘md5.h’
/* File: MD5_H
#define
MD5_H
#ifdef
typedef #else typedef
/*
‘md5.h’
/* (New File) #ifndef
*/
*/
*/
__alpha
unsigned
int
uint32;
unsigned
long uint32;
#endif struct
MD5Context
{ uint32 buf [4]; uint32 bits[2]; unsigned char in[64];
$; void
MD5Init
(struct
MD5Context
void MD5Update unsigned len);
(struct
void MD5Final
(unsigned
void
MD5Transform
*context);
MD5Context
*context,
char digest[16],
(uint32
buf[4],
to make
RSAREF
unsigned
struct
uint32
const
char
MD5Context
const
*context);
in[16]);
/*
* This
is needed
*/ typedef
#endif
struct
/*
MD5Context
!MD5_H
*/
MD5_CTX;
happy
on some
MS-DOS
*buf,
compilers.
527
a7
/*
528
*/
/*
fee bai ve
omdsuc?
/* (New File)
PGP
Source
Code
+/
*/
es*
This code implements the MD5 message-digest algorithm. The algorithm is due to Ron Rivest. This code was written by Colin Plumb in 1993, no copyright is claimed. This
code
is
in the
public
domain;
do
with
it
what
you
wish.
Equivalent code is available from RSA Data Security, Inc. This code has been tested against that, and is equivalent, except that you don’t need to include two pages of legalese with every copy. To
compute
the
MD5Context
message
structure,
digest pass
it
of
a chunk
to
MD5Init,
of bytes, call
declare
MD5Update
needed on buffers full of bytes, and then call MD5Final, fill a supplied i6-byte array with the digest.
which
eH KN OF etwill ee HH ee
*/ #Hinclude
#include
"md5.h"
#ifndef #define
HIGHFIRST byteReverse(buf,
#else void byteReverse #ifndef
/* for memcpy()
len)
(unsigned
*/
/* Nothing
char
*buf,
*/
unsigned
longs);
ASM_MD5
/*
* Note:
this
code
is
harmless
on
little-endian
machines.
*/ /*
byteReverse £7, void
byteReverse Wants2e do
(unsigned
char *buf,
unsigned
longs)
ce
af t =
(uint32)
((unsigned)
buf[1]
s(Qhlabaigey buf
while
\; #endif #endif
+=
((unsigned)
ts) Joybee = 46
4;
(--longs) ;
buf[3]
buf[2] = Ox98badcfe;
ctx->buf [3] = 0x10325476; ctx->bits[0] = 0; Gtx=>bits [1 = 0;
> /* * Update context * of bytes.
to reflect
the
concatenation
MD5Context
*ctx,
of
another
buffer
full
*/ void MD5Update
(struct
unsigned
char
const
*buf,
WINGS 2s te
/* Update t =
$f
bitcount
ctx->bits[0];
((ctx—>bits([0] ctx->bits[1i]++;
ctx->bits[1]
t =
*/
+=
= t + C(uint32) len
(t >> 3) & Ox3f;
/* Handle
29;
/* Bytes
any leading
already
odd-sized
chunks
in shsInfo->data
*/
if (t) {
unsigned
char
te=e645—e¢
5
*p =
(unsigned
char
*) ctx->in .
ifs (iensbuf, (uint32 but len
+= -=
t; t;
*)
ctx->in);
+ t;
*/
unsigned
len)
529
*/
/*
530
*/
/* Process
/*
data
in 64-byte
while (len >= 64) { memcpy (ctx->in,
buf,
chunks
+= -=
Source
Code
and
Internals
*/
64);
byteReverse (ctx->in, 16); MD5Transform (ctx->buf, (uint32 buf len
PGP
*) ctx->in);
64; 64;
N
/* Handle memcpy
any remaining bytes of data.
(ctx->in,
buf,
*/
len);
} /* * Final wrapup * 1 0* (64-bit
- pad to 64-byte boundary with the bit count of bits processed, MSB-first)
pattern
*/ void
MD5Final
(unsigned
char digest[16],
struct
MD5Context
*ctx)
Sh unsigned unsigned
count; char *p;
/* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & Ox3F; /* Set the first char of padding always at least one byte free p = ctx->in + count; *pt+ = 0x80;
/* Bytes COUN
of padding needed
te=sO40—
ela
to 0x80. */
to make
This
64 bytes
is safe
since
there
*/
eCOUNtr
/* Pad out to 56 mod it (count in, 16); MD5Transform (ctx->buf, (uint32 *) ctx->in);
/* Now fill memset
the next
(ctx->in,
0,
block 56);
with 56 bytes
*/
to
64 bytes
*/
is
*/;
/*
File:
‘md5.c’
*/
/* Pad block memset
/* Append
to 56 bytes
(p, 0,
byteReverse
count
(ctx->in,
length
((uint32 ((uint32
/*
14);
in bits
and transform
*) ctx->in)[14] *) ctx->in)[15]
MD5Transform
*/
- 8);
(ctx->buf,
*/
= ctx->bits[0]; = ctx->bits[1]; (uint32
*) ctx->in);
byteReverse ((unsigned char *) ctx->buf, memcpy (digest, ctx->buf, 16); memset
(ctx,
0,
sizeof
(ctx));
4);
/* In case
it’s
sensitive
*/
r #ifndef /* The
ASM_MD5 four
core
functions
- Fi
is optimized
somewhat
*/
pevrdetine Fi(x, y,. 2) (x & y | (3x fiz) e+/ Hdefaneshi(xy sy, 212. (x & ytgez) p> Hdefine F2(s ay, 2) Fiz, x57)
tdefine #define
F3(x, F4(x,
-y, 0
*/ #define
TLOOP(s)
#define
TLOOP1i(s)
if ((unsigned 1
if
(t)
do
TLOOPi(s)
{ s;
} while
(--t)
long) dst < (unsigned long)
src)
/*
* Copy
forward.
*/ t =
if
(int) src; ((t | (int)
/* only need low bits dst) & wmask)
*/
/*
* Try to align operands. This * unless the low bits match.
*/ if ((t ~*~ (int) t = else
dst) & wmask
length;
t = wsize - (t & wmask); length == t; TLOOP1 (*dst++ = *srct+t);
cannot
be done
|| length < wsize)
*/
539
*/
/*
540
*/
/*
PGP
Source
/*
* Copy whole
words,
then mop
up any trailing
t = length / wsize; TLOOP (*(word *) dst
= *(word
*) src;
bytes.
+i, src
+=
wsize;
dst += wsize); t = length & wmask; TLOOP (*dst++ = *srct+t);
/* * Copy backwards. * Alignment works
* (t&wmask)
bytes
+/
Otherwise as before,
to align,
essentially except that
the.same. it takes
not wsize-(t&wmask).
src += length; dst += length; teint) msnce
if ((t if ((t ~
| (int)
(int)
dst) & wmask)
dst)
& wmask
|| length 0)
defaults
*/
#endif
if
(screen_lines screen_lines
if
==
(screen_columns screen_columns
#endif
0) /* nothing
worked,
use
= DEFAULT_LINES; =
== DEFAULT_COLUMNS ;
/* UNIX */
i #ifdef
#define #define
ATARI
reverse_attr() printf("\033p") norm_attr() printf("\033q")
#else
#define #define
reverse_attr() norm_attr()
#endif
#ifdef
VMS
char pager[80] = Helse /* not VMS char pager[80] = #Hendif /* not VMS /* Blort a file terminators,
chars */
"Type/Page"; */ ""; */
/* default
more_file */ int
(char
*fileName)
FILE *inFile; intelinesu—Onmichw
long fileLen;
for VMS
*/
to the screen with page breaks, intelligent handling of line truncation of overly long lines, and zapping of illegal
/*
more_file
pager
ea charsm—mO
smc:
*/
/*
File:
char char
‘more.c’
*/
/*
547
cmd[MAX_PATH] ; buf[16];
int lineno; char *p;
if
((inFile
= fopen
/* Can’t return
tread
if
(fileName,
see how this
FOPRBIN))
could fail
==
NULL)
since we just
created
the file
*/
-1;
(but,
15.16,
inFile);
(compressSignature
((byte
*) buf)
>= 0)
4 fprintf (pgpout, LANG ("'\n\007File fileName) ; recipe
hs) is not a text ao oat
cannot
display.\n"),
als
/* PAGER set set PAGER
in config.txt in config.txt
if (pager[0]
==
a
if
file;
overrides environment variable, to ’pgp’ to use builtin pager */
’\0’)
((p = getenv
("PAGER"))
!= NULL)
strncpy (pager, p, sizeof (pager) - 1); } if (strcmp (pager, "cat") == 0) 4. fclose (inFile); writePhantomOutput (fileName); return
/* Use
0;
built-in
pager
this
currently
real
filename
if
((strcemp
a #ifdef return
fclose
anymore
(fileName,
&& (strlen
if PAGER
doesn’t
(pager)
set
or
_CONSOLE
if this
is for
your
eyes
filename
isn’t
used
as
*/
!= 0) && strcmp
!= 0)
("pgp",
(inFile);
UNIX if (strchr
(fileName,
’\’’)
!= NULL)
-1;
(cmd,
"%s
sprintf
(cmd,
"%s 4s",
(p = cmd; ’/’) +pe=2\\? ;
*p; ++p)
#ifdef
the
CONSOLE_FILENAME)
sprintf
#else
is not
work,
’%s’",
MSDOS
for if (*p == #endif #endif
fflush return
(pgpout); system (cmd);
pager,
pager,
fileName) ;
fileName) ;
pager))
only,
the
#/
548
#ifdef
*/
;
/*
PGP
Source
Code
and
UNIX
if ('isatty (fileno (stdout))) at fclose (inFile); writePhantomOutput (fileName) ; return
0;
} #Hendif
/* UNIX
*/
getScreenSize
();
/* Get file length */ fseek (inFile, OL, SEEK_END); fileLen = ftell (inFile); rewind (inFile); lineno
=
1;
ttycbreak putcharz
(); (?\n”)%
fon (% ) {
ch = getc (inFile); if (ch == LF)
lines++;
putchar
(’\n’);
chars
0;
=
++lineno;
elseuite(ch
==
CR)
lines++;
putchar
(@An”);
chars = 0; ++lineno;
/* Skip following if
((ch
= getc
ungetc
(ch,
else /* Legal
putchar lees)
LF if there
(inFile))
*/ != EOF)
or tab,
char)
print
ch >=’
’? && ch != EOF)
|| ch == TAB)
it */
(ch);
GS
(in S=
/* If we’ve
GN)
reach
@ fs} 8 als
the max.no
of columns
rest of the line */
if
ch
inFile);
if (((unsigned char
is one
!= LF &&
(chars
==
screen_columns
-
1)
we
can handle,
skip the
Internals
sil
File:
‘more.c’
chars
=
while
((ch = getc
if
*/
/*
0;
(inFile))
!= CR && ch != LF && ch
!= EOF);
(ch != EOF) ungetc (ch, inFile); /*
If
we’ve
user while
(ch ==
/* Print
prompt
reverse_attr af
a¢ch) ==
printf
reached
to hit
the
max.no
EOF
|| lines
==
at end of screen
we
can
handle,
("\nDone...hit
screen_lines
-
c = to_upper
--
%d%%
--
new
line\
any key\r"));
Hit
space
for
next
screen,
Enter
/ fileLen);
(c);
/* Blank
out prompt
*/
retope (2b
Op. al & 7S).
sins),
putcnar (7, ?)5 putchar . screen_lines)
*/
int seek_line = lineno lineno = 1; rewind (inFile);
(seek_line
-
2 * screen_lines
+ 3;
> 1)
BLinbiv, 7a Skipping \n "yi; while ((ch = getc (inFile)) (che==)\n”) if (++lineno ==
!= EOF)
seek_line)
break;
Chas Ou lines = 0; else
{ if
for
*/
( ("More
G = getch ();
goto
the
1)
norm_attr (); fflush (stdout);
if
for
mi
7Q’? to quit --\r"), (100 * ftell (inFile))
if
wait
EOF)
(LANG
en
LANG
rows
();
else
printi
of
a key */
(c ==
*Q’'
|| ch
2
[ive s2
done;
Gf (cve=
==
EOF)
*\n2el|
cee
7\r?
I -c ==
73")
549
*/
/*
550
*/
lines -= lines
/*
(c ==» */
*) ? screen_lines
PGP
Source
Code
- 2 ; 1; /* Do n more
5 } done:
ttynorm
();
fclose
(inFile);
return
0;
} /* more_file
*/
/*
* open_more()
and close_more()
redirect
pgpout
to the pager.
*
*/ static
char
static static
boolean piping = FALSE; FILE *savepgpout ;
*mfile
=
NULL;
/*
Sree
pee
*
int
open_more #ifdef char #tendif
(void)
UNIX *p;
if (mfile
|| piping)
close_more savepgpout #ifdef UNIX
fflush
= pgpout;
(pgpout) ;
if (pager[0]
{
if
strncpy ay /* Use
();
==
’\0’)
((p = getenv
(pager,
("PAGER"))
p, sizeof
built-in
pager
(pager)
if PAGER
!= NULL)
- 1); is not
set
or
set
to
if ((strlen (pager) != 0) && strcmp ("pgp", pager) ) al if ((pgpout = popen (pager, "w")) != NULL) piping
= TRUE;
return
0;
"pgp"
*/
and
Internals
*/,
/*
File:
‘more.c’
*/
perror
("popen");
Pgpout
=
/*
savepgpout ;
#endif
if ((mfile = tempfile return
(TMP_TMPDIR
| TMP_WIPE))
== NULL)
-1;
pis SO
= fopen
Pgpout
=
rmtemp
(mfile);
return
-1;
(mfile,
FOPWTXT))
== NULL)
savepgpout ;
} /* user will not see anything until close_more() fprintf (savepgpout, LANG celts a moment..."')); fflush (savepgpout); 2
}
return
0;
/*
close_more */ int
close_more (void) 7 if (!mfile && !piping) return
#ifdef
0;
UNIX
if (piping) pclose
(pgpout);
else
#endif fclose pgpout
if
=
(pgpout); savepgpout ;
(mfile)
{
fprintf
(pgpout,
more_file
rmtemp mfile
(mfile); =
NULL;
}
}
(mfile);
piping
= FALSE;
return
0;
"\n");
is called
*/
551
*/
/*
552
*/
/*
PGP
Source
Code
and
Internals
id On tet f tebasleraemp
/
/* (New File) */ /*
C include
file
for MPI
library
I/O routines
(c) Copyright 1986 by Philip Zimmermann. All rights reserved. The author assumes no liability for damages resulting from the use of this software, even if the damage results from defects in this software.
No warranty
is
expressed
or
implied.
These routines are for multiprecision arithmetic I/O functions for number-theoretic cryptographic algorithms such as ElGamal, Diffie-Hellman, Rabin, or factoring studies for.large composite numbers, as well as Rivest-Shamir-Adleman (RSA) public key cryptography. The external data representation for RSA messages and keys that some of these library routines assume is outlined in a paper by Philip Zimmermann, ''A Proposed Standard Format for RSA Cryptosystems", IEEE
Computer,
September
Some revisions was published. NOTE:
Fi
This
on
to this
assumes
mt
1986,
data
previous
rm
Vol.
format
19 No.
have
inclusion
Byte ordering
#ifdef #undef #endif
NEEDSWAP NEEDSWAP
/* make
sure
NEEDSWAP
of
Stull
/* XLOWFIRST is defined iff external file /* #define XLOWFIRST defined if external is
9,
pages
occurred
21-34.
since
the paper
"mpilib.h"'
q—q-e---—===4—-— ae */
format is LSB-first byteorder byteorder is LSB-first */ initially
undefined
*/
*/
/* Assume MSB external byte ordering */ #ifndef
HIGHFIRST
#define
NEEDSWAP
/* External/internal
byteorder
differs,
need byte swap */
#endif
word16
fetch_wordi6
/*
Fetches a 16-bit word from where byte pointer points to external-format byteorder array. */
buf
byte *put_wordi16 /*
(byte * buf);
(word16
is pointing.
w, byte * buf);
Puts a 16-bit word to where byte pointer is pointing, returns updated byte pointer. buf points to external-format byteorder array. */
word32
fetch_word32
/*
Fetches a 32-bit word from where byte pointer points to external-format byteorder array. */
buf
and
(byte * buf); is pointing.
*/
/*
File:
‘mpiio.h’
byte *put_word32
= */
(word32
/*
553
w, byte * buf);
/*
Puts a 32-bit word to where byte pointer is pointing, and returns updated byte pointer. _ buf points to external-format byteorder array. */ /* Note that convert_byteorder does nothing if internal native byteorder is already the same as external byteorder. */ #ifdef NEEDSWAP /* External/internal byteorder differs, need byte swap
#define #define
convert_byteorder(buf,bytecount) hiloswap(buf ,bytecount) mp_convert_order(r) hiloswap(r,units2bytes(global_precision) )
#else #define
convert_byteorder(buf,bytecount)
#define mp_convert_order(r) #Hendif /* not NEEDSWAP */
#include #ifdef
/* nil
/* nil statement
statement
*/
*/
*/
EMBEDDED
int putchar
(int c);
#endif /* EMBEDDED */
/* standard
C library function
from
*/
int string_length (char *s); /* Returns string length */ int str2reg
(unitptr reg,
/* Converts
a possibly-signed
Returns
assumed
radix,
string digitstr);
int display_in_base (string s, /* Display n in any base, such
of digits.
digit
derived
string
from
unitptr as base
void
(register
checksum
cbc_xor
/* Performs
number.
*/
*/
checksum
/* Returns
a large binary ’h’,’o’,b’,’.’
n, short radix); 10. Returns number
void mp_display (string s, unitptr r); /* Display register r in hex, with prefix word16
into
suffix
byteptr
of buffer.
(register unitptr the
XOR necessary
buf,
string
register
s.
*/
word16
count);
*/ dst, for
register unitptr
RSA
Cipher
Block
void hiloswap (byteptr ri, short numbytes); /* Reverses the order of bytes in an array of bytes.
src,
word16
Chaining.
bytecount);
*/
*/
short mpi2reg (register unitptr r, register byteptr buf); /* Converts to unit array from byte array with bit length prefix
word.
*/
short reg2mpi (register byteptr buf, register unitptr is /* Converts from unit array to byte array with bit length prefix word. */ ARoa end of MPI 1/0 Library Heb Ed eso
ok /
*/
/*
554
*/
/*
/* File: /* (New File) /*
PGP
Source
Code
and
Internals
iMplioa? */ */
mpiio.c - C source code for multiprecision Implemented Nov 86 by Philip Zimmermann Last revised 13 Sep 91 by PRZ
integer
I/O routines.
Boulder Software Engineering 3021 Eleventh Street Boulder, CO 80304 (303) 541-0140
(c) Copyright 1986-1994 by Philip Zimmermann. All rights reserved. The author assumes no liability for damages resulting from the use of this software, even if the damage results from defects in this software. No warranty is expressed or implied. These routines are for multiprecision arithmetic I/0 functions for number-theoretic cryptographic algorithms such as ElGamal, Diffie-Hellman, Rabin, or factoring studies for large composite
numbers,
as well
as Rivest-Shamir-Adleman
(RSA)
public
key
cryptography.
The external data representation for RSA messages and keys that some of these library routines assume is outlined in a paper by Philip Zimmermann, ''A Proposed Standard Format for RSA Cryptosystems", IEEE
Computer,
Some revisions was published.
September
to
this
1986,
data
Vol.
format
19
have
No.
9,
pages
occurred
21-34.
since
the
paper
*/ /* #define DEBUG */ #ifndef EMBEDDED /* not embedded target */
#include
EMBEDDED
/* for printf,
#else /* EMBEDDED - compiling #define NULL (VOID *)O #endif #include #include #include
static
- not
for
etc.
compiling
for
*/
embedded
target
*/
"mpilib.h" "mpiio.h" "pgp.h''
void puthexbyte
(byte b); /* Put out byte
in ASCII
static
void puthexwi6
(wordi6
high byte first.
static void putstr
(string
*/ s);
w);
/* Put out
/* Put
out
16-bit
word
null-terminated
in hex, ASCII
hex via putchar.
*/
*/
Ye
BPUVetMAE
ypiiove>
«7.
/*
string via putchar. */ [*------------—-—-- Following procedures
relate
to I/0 ------------------ */
/*
string_length */ /* Returns
string length,
just like strlen()
from
*/
int
string_length 3: intr sh = if
(char *s)
13 (08 (s != NULL)
while
(*s++)
Beery
return
(i);
} /* string_length
*/
/*
ctox */ #ifdef
DEBUG
/* Returns static
ctox
integer
0-15
if c is an ASCII
hex digit,
-1 otherwise.
*/
int
(int c)
ifeC(ce>=5702)488
(co= %a’) && (ce
*/
3)
(n)
#endif #ifdef
UNIT16
typedef typedef
wordi6 unit; short signedunit;
#define
UNITSIZE
#define
LOG_UNITSIZE
#define #define #define #define #define
uppermostbit ((unit) 0x8000) BYTES_PER_UNIT 2 /* number of bytes in a unit */ units2bits(n) ((n) 4)
#define
bytes2units(n)
16 /* number
of bits
in a unit
*/
4
(((n)+1)
>>
1)
Internals
*/
*/
typedef typedef #define
(((n)+7)
and
*/
an unusual wide, then be
multiply
algorithm
enable
16-bit
Source
*/
/*
/*** CAUTION: power of 2 (8,
#ifdef
Smith’s
/* default--use
symbol
PGP
*/
a
*/
f®
agFilesdefmpilib.h?
»»+/
/*
569
#Hendif
#ifdef
UNIT32
typedef typedef #define
word32 unit; long signedunit; UNITSIZE 32 /* number
#define
LOG_UNITSIZE
#define #define #define
uppermostbit ((unit) 0x80000000L) BYTES_PER_UNIT 4 /* number of bytes in a unit */ units2bits(n) ((n) bytes2units(n) (((n)+3) >>
5) 2)
#define
power_of_2(b)
(b))
/*
Some
((unit)
#define bits2bytes(n)
(((n)+7)
C compilers
expressions
at
of bits
in a unit
1 > 3)
/* computes
(like the ADSP2101)
compile
time
if the
/*
bytes2units(n) BYTES_PER_UNIT
LOG_UNITSIZE
/* #define
is
the
log
UNITSIZE */
units2bytes(n)
/* #define
bytes2units(n)
/* #define bits2units(n) typedef
#ifdef
unit
always
contain
+*/ of bits
bit masks
collapse
in a unit
base
2 of
((n)
(LOG_UNITSIZE-3))
*/
((r)+(prec)-1)
make_lsbptr(r,prec) (r) = lsbptr(r,prec) unmake_lsbptr(r,prec) (r) = ((r)-(prec)+1) msbptr(r,prec) (r) make_msbptr(r,prec) /* (r) = msbptr(r,prec) macro
units
(((n)+(UNITSIZE-1)) >> LOG_UNITSIZE) */
#define tohigher(n) (-(n)) /* offset towards higher unit */ #define pre_higherunit(r) (--(r)) #define pre_lowerunit(r) (++(r)) #define post_higherunit(r) ((r)--) #define post_lowerunit(r) ((r)++) #define bit_index(n) (global_precision-bits2units((n)+1))
#define
*/
*//* fast multiply by
*unitptr;
definitions
constant
shift
HIGHFIRST
/* these
*/
bits2units((n) 3) */
units2bits(n)
/* #define
*/
power-of-2
will not
expressions
operators. */ /* #define uppermostbit power_of_2(UNITSIZE-1) /* #define UNITSIZE units2bits(1) number /* #define /* #define
*/
5
*/
rescale(r,current_precision,new_precision)
rescales
*/
*/
/*
570
*/
/*
PGP
Source
Code
and
a multiprecision integer by adjusting r and its precision to new It can be used to reverse the effects of the normalize routine given above. See the comments in normalize concerning
Intel
vs.
Motorola LSB/MSB
Internals
values.
conventions.
WARNING: You can only safely call rescale on registers that you have previously normalized with the above normalize routine, or are known to be big enough for the new precision. You may specify a new precision that is smaller than the current precision. You must be careful not to specify a new_precision value that is too big, or which adjusts the r pointer out of range.
*/
#define
rescale(r,currentp,newp)
r -=
((newp)
-
(currentp))
/* The macro normalize(r,precision) "normalizes" a multiprecision integer by adjusting r and precision to new values. For Motorola-style processors (MSB-first), r is a pointer to the MSB of the register, and must be adjusted to point to the first nonzero unit. For Intel/VAX-style (LSB-first) processors, r is a pointer to the LSB of the register, and must be left unchanged. The precision counter is always adjusted, regardless of processor type. In the case of precision = 0, r becomes undefined.
*/ #define
normalize(r,prec)
\
{ prec = significance(r); #Helse
/* LOWFIRST
/* these
byte
definitions
r +=
order
assume
(global_precision-(prec));
*/
LSB
comes
first
*/
#define #define #define #define #define #define #define
tohigher(n) (n) /* offset towards higher unit pre_higherunit(r) (++(r)) pre_lowerunit(r) (--(r)) post_higherunit(r) ((r)++) post_lowerunit(r) ((r)--) bit_index(n) (bits2units((n)+1)-1) lsbptr(r,prec) (r)
#define
make_lsbptr(r,prec)
#define #define #define
unmake_lsbptr(r,prec) /* (r) = (r) */ msbptr(r,prec) ((r)+(prec)-1) make_msbptr(r,prec) (r) = msbptr(r,prec)
#define #define
rescale(r,currentp,newp) /* nil statement normalize(r,prec) prec = significance(r)
/*
#endif /* LOWFIRST byte order [Boe aa el aS SEES End byte /*
ch
(r)
= lsbptr(r,prec)
*/ ordering
stuff
bitptr(r,n)
&((r) [bit_index(n)])
*/
*/
*/
-----------------= 0) mp_sub(r,m) /* Prevents r from getting bigger than modulus m */ #define
testeq(r,i)
( (lsunit(r)==(i)) #define
\
&& (significance(r)1)
)
#define testge(r,i) \ ( (lsunit(r)>=(i)) || (significance(r)>1)
)
#define
testle(r,i)
( (lsunit(r)3)
SLOP_BITS is how many "carry bits"' to allow for intermediate calculation results to exceed the size of the modulus. It is used by modexp to give some overflow elbow room for modmult to use to perform modulo operations with the modulus. The number of slop bits required is determined by the modmult algorithm. The Russian peasant modmult algorithm only requires 1 slop bit, for example. Note that if we use an external assembly modmult routine, SLOP_BITS may be meaningless or may be defined in a non-constant manner.
*/
/*
oFile:}al'
npilib.h?
»5*/
/*
#define #define #define
PEASANT_SLOP_BITS 1 MERRITT_SLOP_BITS UNITSIZE UPTON_SLOP_BITS (UNITSIZE/2)
#ifdef
mp_smul
/* old version
requires
MS word = 0 */
#define SMITH_SLOP_BITS UNITSIZE #else /* mp_smula or C version of mp_smul #define SMITH_SLOP_BITS 0
#endif
/* mp_smul
/*
must
integer
be
*/
*/
MAX_BIT_PRECISION It
less
than
multiple
is upper
32704
limit
bits,
or
that
4088
assembly
bytes.
It
primitives should
be
can an
of UNITSIZE*2.
*/ #if
(SLOP_BITS
#define #telse #define #endif #define #define
> 0)
MAX_BIT_PRECISION
(2048+(2*UNITSIZE) )
MAX_BIT_PRECISION
2048
MAX_BYTE_PRECISION MAX_UNIT_PRECISION
(MAX_BIT_PRECISION/8) (MAX_BIT_PRECISION/UNITSIZE)
/* global_precision is the unit extern short global_precision;
/* They
The are
modulo,
wat
#define
"bit used
precision
last
set
by set_precision
sniffer" macros all begin sniffing at the MSB. internally by all the various multiply, divide,
exponentiation,
and
sniff_bit(bptr,bitmask)
square
root
(*(bptr)
functions.
& bitmask)
#define init_bitsniffer(bptr,bitmask,prec,bits) { normalize(bptr,prec); \
if@('prec)"
\
\
return(0);
\
bits = units2bits(prec); \ make_msbptr(bptr,prec); bitmask = uppermostbit; while (!sniff_bit(bptr,bitmask)) \ { bitmask >>= 1; bits--; \ pay
\
;
#define bump_bitsniffer(bptr,bitmask) { if (!(bitmask >>= 1)) \
{ bitmask
573
= uppermostbit;
post_lowerunit(bptr); Ade } /* bump_2bitsniffers
\
\
\
is used
internally
by mp_udiv.
*/
*/
handle.
*/,
/*
574
*/
/*
#define bump_2bitsniffers(bptr,bptr2,bitmask) { if (!(bitmask >>= 1)) \ { bitmask = uppermostbit; \ post_lowerunit(bptr); \ post_lowerunit(bptr2); \ aN $
PGP
Source
boolean
Internals
*/
unitptr r2, register boolean r2 to ri, result in ri */
carry);
unitptr
borrow) ;
mp_subb
(register
unitptr
/* multiprecision
ri,
register
subtract
with borrow,
r2,
*/
boolean mp_dec (register unitptr r); /* Decrement multiprecision integer r.
*/
void mp_neg (register unitptr r); /* Compute 2’s complement, the arithmetic
boolean
result
ri, register in ri. */
unitptr ri, register *r2, and returns -1,
boolean mp_inc (register unitptr r); /* Increment multiprecision integer r.
ri,
in ri
r1, register boolean carry, result in ri.
void mp_shift_right_bits (register unitptr /* multiprecision shift right bits, result short mp_compare (register /* Compares registers *r1,
register
r2 from
boolean mp_rotate_left (register unitptr /* multiprecision rotate left 1 bit with
#ifndef
and
\
/* stuff_bit is used internally by mp_udiv and mp_sqrt. #define stuff_bit(bptr,bitmask) *(bptr) |= bitmask boolean mp_addc (register unitptr ri, register /* multiprecision add with carry
Code
short
of r */
mp_move
#define mp_move(d,s) memcpy ((void*)(d), units2bytes(global_precision) )
(void*)(s),
#endif #ifndef #define #endif
unitfill0o unitfill0(r,ct)
#ifndef
mp_burn
#define #define #endif
mp_burn(r) mp_init(r,0) /* for burning mp_initO(r) mp_init(r,0)
memset((void*)(r),
\
0, units2bytes(ct))
the
evidence
carry); */
bits);
unitptr r2); 0, or 1 */
negative,
*/
*/
gi
/*
File:
#define
‘mpilib.h’
empty_array(r)
void mp_init (register /* Init multiprecision
+/
/*
unitfillO(r,
sizeof(r)/sizeof(r[0])/sizeof(unit) )
unitptr r, wordi6 value); register r with short value.
*/
short significance (register unitptr r); /* Returns number of significant units in r */ int mp_udiv (register unitptr remainder, register unitptr register unitptr dividend, register unitptr divisor);
/* Unsigned
divide,
treats
both operands
as positive.
quotient,
*/
int mp_recip (register unitptr quotient, register unitptr divisor); /* Compute reciprocal as 1/divisor. Used by faster modmult. */
int mp_div (register unitptr remainder, register unitptr quotient, register unitptr dividend, register unitptr divisor); /* Signed divide, either or both operands may be negative. */ wordi6 mp_shortdiv (register unitptr quotient, register unitptr dividend, register word16 divisor) ; /* Returns short remainder of unsigned divide. */
int mp_mod (register unitptr remainder, register unitptr dividend, register unitptr /* Unsigned
divide,
treats
both
operands
divisor); as positive. */
wordi6 mp_shortmod (register unitptr dividend, register /* Just returns short remainder of unsigned divide. */
word16
divisor) ;
int mp_mult (register unitptr prod, register unitptr multiplicand, register /* Computes
multiprecision
prod
unitptr multiplier) ; = multiplicand * multiplier */
int countbits (unitptr r); /* Returns number of significant
bits
int int int
stage_peasant_modulus (unitptr n); stage_merritt_modulus (unitptr n); stage_upton_modulus (unitptr n);
int
stage_smith_modulus
/* Must int
pass
modulus
*/
(unitptr n); stage_modulus
before
calling
modmult.
peasant_modmult (register unitptr prod, unitptr multiplicand, register unitptr multiplier);
int merritt_modmult unitptr
(register unitptr prod,
multiplicand,
int upton_modmult int
to
in r.
register
unitptr
multiplier);
(register unitptr prod,
unitptr multiplicand, register unitptr smith_modmult (register unitptr prod, unitptr multiplicand, register unitptr
multiplier) ; multiplier) ;
*/
5875
*/
/*
576
*/
/* Performs
/*
combined multiply/modulo
operation,
PGP
Source
exponentiation/modulo
int mp_modexp_crt (unitptr expout, unitptr p, unitptr q, unitptr /* exponentiation and modulo using
/FRRRRR ERK RK ERR
end Of MPI
algorithm.
and
with global modulus
int mp_modexp (register unitptr expout, register unitptr register unitptr exponent, register unitptr modulus);
/* Combined
Code
Internals
*/
expin,
*/
unitptr expin, ep, unitptr eq, unitptr u); Chinese Remainder Theorem */
Library
222K
/
*/
ie - OF ilecen=
(Guansiy))
(aseal))))s
else
5@ Ee egal
ca fae4e
carry = (x < *r1); post_higherunit (r2); *post_higherunit (ri) = x; return carry; /* return } /* mp_addc */ #e
ndif
/* mp_addc
#i fndef
the final
carry flag bit
*/
*/
mp_subb
/*
multiprecision subtract with borrow, r2 from ri, result in ri borrow is incoming borrow flag-- value should be 0 or 1 *
/
/*
boolean mp_subb */ bo olean
mp_subb
(register
unitptr
ri,
register
unitptr
r2,
register
ip register short
unit
x;
precision;
/* number
of
precision = global_precision; make_lsbptr (ri, precision) ; make_lsbptr (r2, precision);
while
(precision-—)
if
Xoo
(borrow)
ST
eed
[Xonaratoyn? =
oe
(Gagel =
cag) 2
else
> aS
al en
leepaagoyy =
3aA
(Geel
> UNITSIZE;
#endif
} /* mp_init
*/
/*
Significance */
/* Returns
number
of significant
units
short
significance
= 0)
mp_sub (remainder, divisor) ; stuff_bit (quotient, bitmask); bump_2bitsniffers return
#define
quotient,
bitmask) ;
0;
} /* mp_udiv #ifdef
(dividend,
*/
UPTON_OR_SMITH RECIPMARGIN
0 /* extra margin bits
used
by mp_recip()
*/
/*
mp_recip */ /* Compute reciprocal (quotient) as 1/divisor. Used by faster int mp_recip (register unitptr quotient, register unitptr divisor) athe loslieris short qprec;
modmult.
*/
*/
/*
Pacer
mpilibye’
#o7K/
/*
register unit bitmask; unit remainder [MAX_UNIT_PRECISION] if (testeq (divisor, 0))
return mp_initO mp_initO
-1; /* zero divisor (remainder); (quotient) ;
/* normalize
and compute number
bits = countbits bitmask = bitmsk
qprec
divide
of bits
(bits + 1);
(remainder,
(bits
error
*/
in quotient
(divisor) + RECIPMARGIN; (bits); /* bitmask within
= bits2units
mp_setbit
means
;
- RECIPMARGIN)
a single
-
first unit
*/ */
1);
/* rescale quotient to precision of divisor + RECIPMARGIN rescale (quotient, global_precision, qprec); make_msbptr (quotient, qprec); while (bits-——) { mp_shift_left
bits
(remainder) ;
if (mp_compare
(remainder,
divisor)
>= 0)
mp_sub (remainder, divisor); stuff_bit (quotient, bitmask) ; bump_bitsniffer mp_initO return
(quotient,
(remainder);
/* burn
bitmask); sensitive
data
left
on
stack
0;
} /* mp_recip */ #endif /* UPTON_OR_SMITH
*/
/*
mipaty, /* Signed divide, either or both operands may be negative. */ int mp_div (register unitptr remainder, register unitptr quotient, register unitptr dividend, register unitptr divisor)
{ boolean dvdsign, Inte status,
dsign;
dvdsign = (boolean) (mp_tstminus (dividend) != 0); dsign = (boolean) (mp_tstminus (divisor) != 0); if (dvdsign) mp_neg (dividend) ;
if (dsign) mp_neg
status
(divisor) ;
= mp_udiv
(remainder,
quotient,
dividend,
divisor) ;
if (dvdsign) mp_neg
if (dsign)
(dividend);
/* repair
caller’s
dividend
*/
*/
*/
— 887
*/
588
/*
*/
/*
mp_neg (divisor); if (status < 0) return
status;
/* repair
/* divide
caller’s
error?
divisor
PGP
Source
Code
and
Internals
*/
*/
if (dvdsign) mp_neg
(remainder) ;
if (dvdsign ~ dsign) mp_neg (quotient);_ return
status;
} /* mp_div */ /* * * * *
This function does a fast divide and mod on a multiprecision dividend using a short integer divisor returning a short integer remainder. This is an unsigned divide. It treats both operands as positive. It is used mainly for faster printing of large numbers in base 10.
*/ /*
mp_shortdiv */ wordi6 mp_shortdiv register int
(register unitptr unitptr dividend,
quotient, register word16
divisor)
bits;
short dprec; register unit bitmask; register wordi6 remainder;
if (!divisor)
/* if divisor
return -1; /* zero remainder = 0;
divisor
== 0 */ means
divide
error
*/
mp_initO (quotient); /* normalize and compute number of bits in dividend first init_bitsniffer (dividend, bitmask, dprec, bits); /* rescale quotient to same precision (dprec) as dividend rescale
(quotient,
make_msbptr while {
(quotient,
dprec);
dprec);
(bits--)
remainder
if
global_precision,
> #endif /*
Compute
the most
significant
& (qi
1) *+eCq2%>>0i) term
and add
~
q2));
+ 1s in the
others
*/
q = (q >> (MULTUNITSIZE - 2)) + (((dividend[0] q >>=
/*
Prevent
mutemp
ae
=
lsb_factor
(void)
~ MULTUNIT_mask)
* (unsigned
long)
reciph)
= 0) return -3; /* if expin >= modulus, return
if (mp_compare
*/
(exponent,
/* if
modulus)
exponent
>= modulus,
= global_precision;
error
*/
>= 0) /* save
return
error
*/
global_precision
*/
/* set smallest optimum precision for this modulus */ set_precision (bits2units (countbits (modulus) + SLOP_BITS)); /* rescale all these registers to global_precision we just defined rescale (modulus, oldprecision, global_precision) ; rescale (expin, oldprecision, global_precision); rescale (exponent, oldprecision, global_precision) ; rescale (expout, oldprecision, global_precision) ;
if (stage_modulus
(modulus))
set_precision (oldprecision); /* restore original precision return -5; /* unstageable modulus (STEWART algorithm) */
ip /* normalize and compute number of bits in exponent init_bitsniffer (exponent, bitmask, eprec, bits);
first
*/
/* We can “optimize out" the first modsquare and modmult: bits--; /* We know for sure at this point that bits>0 */ mp_move (expout, expin); /* expout = (1*1)*expin; */
*/
bump_bitsniffer
(exponent,
bitmask) ;
*/
*/
+/
/*
File:
while {
‘mpilib.c’
poll_for_break
(); /* polls keyboard,
COUNTMULTS tally_modsquares++;
/* bump
#endif /* COUNTMULTS */ mp_modsquare
:
/*
(bits--)
abort program */ #ifdef
¥*/
if
(product,
(sniff_bit
"number
allows
of modsquares"
counter
*/
expout);
(exponent,
bitmask))
mp_modmult (expout, product, expin); #ifdef COUNTMULTS tally_modmultst++; /* bump "number of modmults"
#endif /* COUNTMULTS */ Ny
ctrl1-C to
~
counter
*/
else
{
mp_move
(expout,
product) ;
bump_bitsniffer
} /* while mp_burn
bits--
(product);
(exponent,
bitmask);
*/ /* burn
the
evidence
modmult_burn (); /* ask mp_modmult own evidence */ #ifdef a
COUNTMULTS
/* diagnostic
long atomic_mults; unsigned int unitcount,
unitcount = bits2units /* calculation assumes
on
the
stack
*/
to also burn its
analysis
*/
totalmults;
(countbits (modulus) ); modsquare takes as long as
a modmult:
*/
atomic_mults = (long) tally_modmults *(unitcount * unitcount) ; atomic_mults += (long) tally_modsquares *(unitcount * unitcount) ; printf ("%1ld atomic mults for ", atomic_mults) ; printf ("%dt+%d = %d modsqrt+modmlt, tally_modsquares, tally_modmults, tally_modsquares + tally_modmults, countbits (modulus), unitcount);
at %d bits,
“%d words.\n",
ty
#endif /* COUNTMULTS */ set_precision /* Do an
will
(oldprecision);
explicit
be forced
copyright_notice
reference
to the
to include return
*/
original precision
copyright
it in the
(); /* has no real
return 0; /* normal } /* mp_modexp */ /*
/* restore
notice
executable
effect
so
that
object
at run time */
*/ the
image...
linker
*/
617
*/
618
~*
*/
/*
PGP
Source
Code
and
This is a faster modexp for moduli with a known factorisation into relatively prime factors p and q, and an input relatively prime to modulus, the Chinese Remainder Theorem to do the computation mod p mod q, and then combine the results. This relies on a number of precomputed values, but does not actually require the modulus n or exponent
expout
this
p2 = (expin q2 = (expin and then
the
(p*q).
by evaluating
~ e) mod p and ~ e) mod q a
combining
the
two
by the
CRT.
Two optimisations of this are possible. modulo p and q before starting.
First,
Second, since we know the factorisation from the factorisation of n = p*q), and
both p and q, to throw away Letting ep = eq = then
two the and
e.
= expin ~ e mod
We form
Internals
we
can
reduce
of p and q (trivially derived expin is relatively prime to
we can use Euler’s theorem, expin~phi(m) multiples of phi(p) or phi(q) in e. e mod phi(p) and e mod phi(q)
combining
these
two
speedups,
we
expin
only need
to
= 1 (mod m),
evaluate
p2 = ((expin mod p) ~ ep) mod p and q2 = ((expin mod q) ~ eq) mod q. Now
we
expout expout
need
to
apply
the
CRT.
Starting
with
= p2 (mod p) and = q2 (mod q)
we can say that expout = p2 + p * k, and if we assume then 0 = 0) return FALSE; /* probably not compressible return
TRUE;
/* possibly
} /* compressible
compressible
8);
*/
*/
*/
/* Possible error exit codes - not all of these are used. Note that don’t use the ANSI EXIT_SUCCESS and EXIT_FAILURE. To make things easier for compilers which don’t support enum we use #defines */ #define EXIT_OK 0 #define INVALID_FILE_ERROR 1 #define FILE_NOT_FOUND_ERROR 2 #define UNKNOWN_FILE_ERROR 3 #define NO_BATCH 4 #define BAD_ARG_ERROR 5 #define INTERRUPT 6 #define OUT_OF_MEM 7 /* Keyring errors: Base value = 10 */ #define KEYGEN_ERROR 10 #define NONEXIST_KEY_ERROR 11
we
*/
ie
aPiLeseeipgpsc!
#define #define #define #define #define #define #define #define
/*
/* Encode
errors:
Base
value
=
20
*/
SIGNATURE_ERROR 20 RSA_ENCR_ERROR 21 ENCR_ERROR 22 COMPRESS_ERROR 23
/* Decode #define #define #define #define
errors:
Base
value
SIGNATURE_CHECK_ERROR RSA_DECR_ERROR 31 DECR_ERROR 32 DECOMPRESS_ERROR 33
= 30 */ 30
SIGINT
/* This case
function is called if a BREAK we zap the temporary files.
signal
is sent
to the
*/ /*
breakHandler */ void
breakHandler cf #ifdef
(int
sig)
UNIX
if (sig == SIGPIPE) cf signal (SIGPIPE, SIG_IGN); exitPGP (INTERRUPT);
a if (sig fprintf else #endif
fprintf
exitPGP #Hendif
643
KEYRING_ADD_ERROR 12 KEYRING_EXTRACT_ERROR 13 KEYRING_EDIT_ERROR 14 . KEYRING_VIEW_ERROR 15 KEYRING_REMOVE_ERROR 16 KEYRING_CHECK_ERROR 17 KEY_SIGNATURE_ERROR 18 KEYSIG_REMOVE_ERROR 19
#define #define #define #define
#ifdef
hed+/
!= SIGINT) (stderr,
"\nreceived
(pgpout,
LANG
(INTERRUPT) ;
signal
("\nStopped
%d\n",
at user
sig); request\n"));
program.
In this
*/
/*
644
*/
/*
PGP
Source
Code
and
Internals
/*
clearscreen */ /*
Clears
static
screen
clearscreen
t
and
homes
the
cursor.
*/
void
(void)
fprintf (pgpout, '\n\033[0;0H\033[J\r fflush (pgpout);
/* We had to process the config file foreign language to translate the
\r");
first to possibly sign-on line that
/* ANSI
sequence.
select the follows...
*/
*/
/*
Signon_msg
*/ static
void
signon_msg
(void)
word32 tstamp; /* display message only once to static boolean printed = FALSE;
if
(quietmode
allow
calling
multiple
times
*/
|| printed)
return;
printed
= TRUE;
fprintf (stderr, LANG ("Pretty Good Privacy(tm) rel_version) ; #ifdef
%s - Public-key
encryption for the masses.\n"),
TEMP_VERSION
fputs,
¢
"Internal
development
version
only
- not
for
general
release.\n",
stderr);
#endif
fprintf
(stderr,
LANG ("(c) 1990-1994 Philip Zimmermann, rel_date) ; fputs (LANG (signon_legalese), stderr); fputs ( LANG
eee
of this
software
may
be
Phil’s
restricted
Pretty
by the
Good
Software.
U.S.
government.\n"),
stderr);
get_timestamp ((byte *) & tstamp); /* timestamp points to tstamp fprintf (pgpout, "Current time: %s\n", ctdate (&tstamp));
#ifdef TEMP_VERSION /* temporary experimental #include #define CREATION_DATE 0x2DCO79A4ul1
version
of PGP
%s\n"),
*/
*/
*/
/*
Filet»
‘pgp.c’
=*/
/*
645
/* CREATION_DATE is Fri
Apr
29
03:06:12
1994
UTC
*/
#define LIFESPAN ((unsigned long) /* LIFESPAN is 60 days */
60L * (unsigned long) 86400L)
/*
SR
SS
/* it this
fe
ed
Be
is an experimental
version
of PGP,
cut
its life
short
*/
TP ERNE kata eed aes (void) ‘ SiGoRs S
Aden,
(NULL)
>
(CREATION_DATE
fprintf (stderr, "\n\007This experimental
version
exit
*/
(-1);
/* error
exit
} /* check_expiration_date */ Helse /* no expiration date */ #define check_expiration_date()
/* -f means
act
/* -i means
internalize
*
as a unix-style filter
between
extended
like
show longer more
/* -m means /* -d means
display decrypt
/* -t
treat
statement
pure
compatible)
descriptive
text
function...
and
expired.\n");
*/
*/ attribute
plaintext output on only, leaving inner
as
/* Used by getopt
file
(or very
/* -1 means means
of PGP has
/* null
#endif /* TEMP_VERSION */
+ LIFESPAN) )
information,
operating
only
systems.
diagnostic messages
supported */
*/
screen, like unix "more" */ signature wrapping intact */
convert
to
canonical
text
format
*/
*/
#define OPTIONS "abcdefghiklmo: prstu: vwxz:ABCDEFGHIKLMO:PRSTU: VWx?7"' extern int optind; extern
boolean
static
char
*optarg;
emit_radix_64
boolean
=
FALSE;
sign flag
boolean
moreflag
boolean
filter_mode
=
/* set
config
file
*/
FALSE;
= FALSE;
static static
boolean boolean
preserve_filename decrypt_only_flag
static
boolean
de_armor_only
static
boolean
strip_sig_flag
boolean boolean
by
= FALSE;
clear_signatures strip_spaces;
=
=
= FALSE; = FALSE;
FALSE;
= FALSE;
TRUE;
static boolean c_flag = FALSE; static boolean u_flag = FALSE; /* Did I get my_name from -u? */ boolean encrypt_to_self = FALSE; /* should I encrypt messages to myself? boolean
batchmode
=
FALSE;
boolean
quietmode
= FALSE;
/*
if
TRUE:
don’t
ask
questions
*/
*/
*/
/*
646
*/
/*
PGP
Source
Code
boolean force_flag = FALSE; /* overwrite existing file without #Hifdef VMS /* kludge for those stupid VMS variable-length
text records char
and
asking
Internals
*/
*/
literal_mode
=
MODE_TEXT;
/* MODE_TEXT
or
MODE_BINARY
for
literal
packet */
#else /* not VMS */ char literal_mode packet */
#Hendif
= MODE_BINARY;
/* MODE_TEXT
or MODE_BINARY
is substring
char my_name[256] in ring */ boolean keepctx /* Ask for each boolean
of default
= "\0O";
userid
/* null my_name
for
secret
means
take
key to make
first
boolean
interactive_add
nomanual
/* If non-zero, makerandom
=
FALSE;
=
0;
=
0;
char *outputfile = NULL; int errorLvl = EXIT_OK;
search
tag */
char plainfile[MAX_PATH] ; int myArge = 2; char **myArgv; struct hashedpw *passwds = 0, *keypasswds = 0; static struct hashedpw **passwdstail = &passwds; /*
main
*/
int
(int argc,
char *argv[])
{ int
status,
before
initialize file to this many random bytes */
static char mcguffin[256]; /* userid boolean signature_checked = FALSE;
main
signatures
userid
= FALSE; /* TRUE means keep .ctx file on decrypt */ key separately if it should be added to the keyring */
boolean compress_enabled = TRUE; /* attempt compression long timeshift = OL; /* seconds from GMT timezone */ int version_byte = VERSION_BYTE_NEW;
static static
literal
/* not VMS */
/* my_name
int
for
opt;
char *inputfile = NULL; char **recipient = NULL; char **mcguffins; char *workfile, *tempf; boolean nestflag = FALSE; boolean decrypt_mode = FALSE; boolean wipeflag = FALSE; boolean armor_flag = FALSE; /* -a option boolean separate_signature = FALSE; boolean keyflag = FALSE; boolean encrypt_flag = FALSE;
*/
encryption
*/
*/
=/
(/*
wBilesvel
pgp.ood +/
/*
boolean boolean
conventional_flag = FALSE; attempt_compression; /* attempt
boolean
output_stdout;
compression
/* Output goes to stdout
char char
*clearfile = NULL; *literal_file = NULL;
char
literal_file_name[MAX_PATH] ;
char
cipherfile[MAX_PATH] ;
*/
before
encryption
char keychar = ’\0’; char *p; byte ctb; struct hashedpw *hpw;
/* Initial messages pgpout
to stderr */
= stderr;
#ifdef DEBUG1 verbose = TRUE; #endif /* * * * * * * *
The various places one can get passwords from. We accumulate them all into two lists. One is to try on keys only, and is stored in no particular order, while the other is of unknown purpose so far (they may be used for conventional encryption or decryption as well), and are kept in a specific order. If any password in the general list is found to decode a key, it is moved to the key list.
* The general * so the tail
list is not grown after initialization, pointer is not used after this.
*/ if
((p = getenv
{
("PGPPASS"))
!= NULL)
hpw = xmalloc (sizeof (struct hashedpw)); hashpass (p, strlen (p), hpw->hash); /* Add to linked list of key passwords hpw->next = keypasswds; keypasswds = hpw;
*/
+ /* * * * *
The -z "password" option should be used instead of PGPPASS if the environment can be displayed with the ps command (eg. BSD). If the system does not allow overwriting of the command line
argument should
list
but
if it has
*/
for’ (opt = 1; opt < argc;
\!
a "hidden"
environment,
be used.
p = argv[opt] ; if#e(pL0] (hepiic?
+topt)
| ileplil]et=sa?zs)
continue;
/* Accept Deter.
if
(!*p)
either
"-zpassword"
or
"-z password"
*/
PGPPASS
*/
647
*/
/*
648
*/
/*
PGP
Source
Code
and
p = argv[+t+opt] ;
/* p now points to password */ if.(!p)
break;
/* End
of arg
list
- ignore
*/
hpw = xmalloc (sizeof (struct hashedpw) ); hashpass (p, strlen (p), hpw->hash);
/* Wipe password */ while *ptte=
(*p)
2a:
/* Add to tail
of linked
hpw->next = 0; *passwdstail =
hpw;
passwdstail
list
of passwords
*/
= &hpw->next;
a /*
* If PGPPASSFD is set in the environment try to read the password * from this file descriptor. If you set PGPPASSFD to O pgp will * use the first line read from stdin as password.
*/ if
((p = getenv
("PGPPASSFD"))
!= NULL)
{ int
if
passfd;
(*p &&
(passfd = atoi
(p)) >= 0)
char pwbuf [256]; p = pwbuf;
while (read (passfd, p, 1) == 1 && *p != ’\n’) a oF hpw = xmalloc (sizeof (struct hashedpw)); hashpass (pwbuf, p - pwbuf, hpw->hash); memset
(pwbuf,
0, p - pwbuf);
/* Add to tail of linked
list
of passwords
*/
hpw->next = 0; *passwdstail = hpw; passwdstail = &hpw->next;
o; /* Process the config file. - Hard-coded defualts - The system config file - Hard-coded defaults for - The user’s config file - Environment variables - Command-line options.
+/
The
following
override
security-critical
opt = 0; /* Number of config files read */ #ifdef PGP_SYSTEM_DIR strcpy (mcguffin, PGP_SYSTEM_DIR) ; strcat (mcguffin, "config.txt"); if (access (mcguffin, 0) == 0)
each
things
other:
Internals
*/
/®
GFibeste‘pepsc?
bol+/
/*
649
opttt;
/* * Note: errors here are.NOT fatal, so * can use PGP with a corrputed system
*7,
processConfigFile
that people file.
(mcguffin) ;
#endif /* * These must be personal; * influence them.
the
system
config
file
may not
*/
buildfilename buildfilename
(globalPubringName, (globalSecringName,
buildfilename
"pubring.pgp"); "secring.pgp");
(globalRandseedName,
my_name[O]
=
/* Process
the
"randseed.bin");
’\0’; config
file
first.
Any command-line
arguments
will
override the config file settings */
#if defined(UNIX)
|| defined(MSDOS)
/* Try “pgp.ini" #ifdef
on MS-DOS
|| defined(0S2)
or ".pgpre"
on Unix */
UNIX
buildfilename
(mcguffin,
".pgprc");
(mcguffin,
"pgp.ini");
#else
buildfilename #endif
;
if (access (mcguffin, 0) != 0) buildfilename (mcguffin, "config.txt"); #else
buildfilename #endif
if (access {
(mcguffin,
(mcguffin,
"config.txt");
0) == 0)
opttt;
if (processConfigFile exit
(mcguffin)
< 0)
(BAD_ARG_ERROR) ;
dy
PeeClopt) fprintf
(pgpout,
init_charset
LANG
("\007No
configuration
file
found.\n")) ;
();
#ifdef MSDOS /* only on MSDOS systems */ if ((p = getenv ("TZ")) == NULL || *p ==
’\0’)
x fprintf
(pgpout,
LANG
("\OO7WARNING:
defined, so GMT timestamps\n\ may be wrong. See the PGP User’s
in AUTOEXEC.BAT file.\n")); }
Guide
Environmental
to properly
variable
define
TZ\n\
TZ
is not
\
*/
650
/*
#Hendif
*/
/*
/* MSDOS
#ifdef VMS #define TEMP
PGP
Source
Code
and
(char
**)))
==
Internals
*/
"SYS$SCRATCH"
#telse
#define
#endif
TEMP
"TMP"
/* VMS
*/
if ((p = getenv (TEMP)) settmpdir (p); if
((myArgv
=
!= NULL && *p != ’\0’)
(char **) malloc
((arge + 2) * sizeof
NULL)
{ fprintf exitPGP
(stderr, (7);
} myArgv[0]
= NULL;
myArgv[i]
= NULL;
LANG
("\n\0070ut
/* Process all the command-line while (optind < argc)
of memory.\n"));
option
/* * Allow random order of options * NOTE: this does not work with * the PGP distribution.
switches:
*/
and arguments (like GNU getopt) GNU getopt, use getopt.c from
e/, if ((opt = pgp_getopt
{
(argc,
argv,
OPTIONS))
== EOF)
if (optind == argc) /* -- at end */ break;
myArgv[myArgct+t+]
= argv[optind+t+];
continue;
, opt = to_lower if (keyflag &&
t
if (keychar
==
keychar else keychar
’V’;
=
(opt); (keychar
==
’\0’
|| (keychar
’v’)
= opt;
continue;
} switch
(opt)
af Casemudia: armor_flag
= TRUE;
emit_radix_64 break;
=
1;
Gasieuubie:
separate_signature break;
= strip_sig_ flag = TRUE;
==
’v’
&& opt ==
’v’)))
#/
Y*
gsEA textal pep:ood */
GAS
/*
OmaGiar
encrypt_flag = conventional_flag c_flag = TRUE;
= TRUE;
break; case ’d’:
decrypt_only_flag
= TRUE;
break; case ’e’:
encrypt_flag break; case Vis filter_mode break; casen irene case ’h’:
usage
= TRUE;
=
TRUE;
();
break;
#ifdef VMS case 742% literal_mode break;
#endif case
/* VMS
= MODE_LOCAL;
*/
’k’:
keyflag break; case ’1’: verbose break; case ’m’:
= TRUE;
=
moreflag
TRUE;
= TRUE;
break;
case ?p’: preserve_filename
= TRUE;
break;
Casicmnows
outputfile
= optarg;
break; case ’s’:
sign_flag
= TRUE;
break; case ’t’: literal_mode break;
case
=
MODE_TEXT;
’u’:
strncpy
(my_name,
optarg,
sizeof
CONVERT_TO_CANONICAL_CHARSET u_flag = TRUE; break;
case
’w’:
wipeflag break;
= TRUE;
(my_name)
(my_name);
- 1);
651
/*
652
*/
/*
PGP
Source
Code
and
Internals
caseeZzis: break;
/* ?+? case
special
option:
does not require
- */
+’;
if (processConfigLine
(optarg)
== 0)
break;
fpranttacstderr,
."\n");
/* fallthrough */ default:
arg_error
();
myArgv[myArgc]
= NULL;
/* Just to make it NULL terminated */
if (keyflag && keychar key_usage ();
signon_msg
==
’\0’)
();
check_expiration_date
(); /* hobble
any experimental
/* * Write to stdout if explicitly asked * no explicit file name was given.
to,
or
version
in filter
mode
*/ and
*/ output_stdout
#if /* /* if
=
outputfile
? strcmp
(outputfile,
"-")
==
0
: filter_mode;
1 At request of Peter Simons, use stderr JIS: Put this code back in... removing
always. Sounds reasonable. */ it broke too many things */
(!output_stdout )
pgpout #endif
=
stdout;
#if defined(UNIX) umask
(077);
|| defined(VMS)
/* Make
files
default
to private
*/
#endif
initsigs (); /* Catch signals */ noise (); /* Start random number generation
*/
if (keyflag) { status
= do_keyopt
(keychar);
if (status < 0) user_error (); exitPGP (status); }
/* -db means break off signature certificate if (decrypt_only_flag && strip_sig_flag) decrypt_only_flag
= FALSE;
into
separate
file
*/
ey
/*
File:
‘pgp.c’
= */
if (decrypt_only_flag decrypt_mode
653
+7,
&& armor_flag)
= de_armor_only
if (outputfile
= TRUE;
!= NULL)
preserve_filename
or
/*
aie
&&
= FALSE;
tencrypt_flag
&&
!conventional_flag
if (wipeflag) { /* wipe only */ if (myArge != 3) arg_error (); /* need one argument */ Sica ia (myArgv[2]) == 0 && remove (myArgv[2]) fprintf (pgpout, LANG ("\nFile %s wiped and deleted.
fprintf
(pgpout,
exitPGP
(EXIT_OK);
&&
!armor_flag)
== 0)
"), myArgv[2]);
"\n");
ip exitPGP
(UNKNOWN_FILE_ERROR) ;
/* decrypt
if none
decrypt_mode
=
if (myArge == 2) { /* no arguments #ifdef
are
specified
+*/
*/
UNIX
if
{
of the -s -e -c -a -w options
TRUE;
(!filter_mode
/* piping * switch
!isatty
(fileno
(stdin) ))
to pgp without
arguments
and no -f:
to filter
but
write
* if it’s a tty, if (!moreflag) pgpout
&&
mode
use
don’t
the preserved
output
filename
to
stdout
*/
= stderr;
filter_mode
if (isatty
=
TRUE;
(fileno
(stdout))
preserve_filename
=
&&
!moreflag)
TRUE;
} #tendif
if
(!filter_mode)
if (quietmode) { quietmode
signon_msg
fprintf LANG
= FALSE;
();
(pgpout, ("\nFor
details
on
licensing
and
distribution,
see
\nFor other cryptography products and custom development \nPhilip Zimmermann, 3021 11th St, Boulder CO 80304 USA,
the
PGP
services, \
User’s
Guide.\
contact:\
/*
654
*/
+1
303
phone
PGP
/*
Source
Code
Internals
and
541-0140\n"));
if (strcmp ((p = LANG ("@translator®")), "@translator") ) fprintf (pgpout, p); fprintf (pgpout, LANG ("\nFor a usage summary, type: pgp —h\n")); exit
(BAD_ARG_ERROR);
/* error
exit
*/
tp if else
t if (filter_mode)
{ recipient
= &myArgv([2];
} else
uf
inputfile recipient
= myArgv([2]; = &myArgv([3];
} 5 if
(filter_mode)
“i inputfile
else
if
{ /* /* * * * * * * * *
=
"stdin";
(makerandom
Create
the
> 0)
input
file
*/
+makerandom=: Create an input file consisting of cryptographically strong random bytes, before applying the encryption options of PGP. This is an advanced option, so assume the user knows what he’s doing and don’t bother about overwriting questions. E.g. pgp tmakerandom=24 foofile Create "foofile" with 24 random bytes in it. pgp t+tmakerandom=24 -ea foofile recipient
* The same, but also encrypt it to * foofile.asc as well. * This feature was created to allow PGP * around for other applications to use.
"recipient",
to
create
and
creating
send
keys
+/ status
=
cryptRandWriteFile
(inputfile,
(struct
IdeaCfbContext
*) 0,
(unsigned) makerandom) ; if (status < 0)
{ fprintie(stderr, exitPGP
“Error
writing file
\“/s\\n"
einputrile) ;
(INVALID_FILE_ERROR) ;
fprintf
(pgpout,
LANG
("File %s created
inputfile, makerandom) ; /* If we aren’t encrypting,
don’t
bother
containing trying
4d random bytes.\n"),
to decrypt
this!
*/
+*/
/*
File:
‘pgp.c’?
= ¥*/
/*
if (decrypt_mode) exitPGP (EXIT_OK); — /* This
is obviously
literal_mode
=
NOT a text
file
+*/
MODE_BINARY;
else
{ if (decrypt_mode
strcpy
(cipherfile,
force_extension
&& no_extension
(inputfile) )
inputfile);
(cipherfile,
ASC_EXTENSION);
if (file_exists (cipherfile)) { inputfile = cipherfile; else
af force_extension if (file_exists
(cipherfile, PGP_EXTENSION) ; (cipherfile) )
4. inputfile
= cipherfile;
hp else
x force_extension if (file_exists inputfile
(cipherfile, SIG SSIS ELE: (cipherfile))
= cipherfile;
} if
fprintf
LANG
(!file_exists
(pgpout,
("\007File
(inputfile))
[%s] does not exist.\n"),
inputfile);
errorLvl = FILE_NOT_FOUND_ERROR; user_error ();
} if (strlen
(inputfile)
>=
(unsigned)
fprintf (pgpout, LANG ("\O007Invalid filename: errorLvl = user_error
} strcpy if
INVALID_FILE_ERROR; ();
(plainfile,
(filter_mode)
inputfile);
MAX_PATH
[%s]
- 4)
too long\n"),
inputfile) ;
655
*/
/*
a
656
/*
setoutdir
(NULL);
/* NULL means
PGP
Source
Code
and
Internals
/,
use tmpdir */
els e
af
if (outputfile)
setoutdir
(outputfile);
else
setoutdir if
(inputfile) ;
(filter_mode) workfile
= tempfile
readPhantomInput
(TMP_WIPE
| TMP_TMPDIR) ;
(workfile);
els e
{
workfile
= inputfile;
get_header_info_from_file
(workfile,
&ctb,
1);
if (decrypt_mode) x strip_spaces
=
FALSE;
if ('is_ctb (ctb) && is_armor_file do_armorfile (workfile);
else
if (do_decrypt
user_error (1);
OL))
< 0)
();
if (batchmode exitPGP
(workfile)
(workfile,
&&
!signature_checked)
/* alternate
success,
file
did not
have
sig.
*/
else
exitPGP }
(EXIT_OK);
/*
*
See if plaintext input file was actually created by PGP earlier-If it was, maybe we should NOT encapsulate it in a literal packet. (nestflag = TRUE). Otherwise, always encapsulate it (default).
*
(Why test
* *
for filter_mode??7)
*/ if
(!batchmode /*
do we
ip else
&&
!filter_mode
&& legal_ctb
(ctb))
Special case--may be a PGP-created packet, so inhibit encapsulation in literal packet? */
fprintf (pgpout, LANG ("\n\007Input file ’%s’ looks inputfile); fprintf (pgpout, LANG ("\nIs it safe to assume that nestflag = getyesno (’n’);
if (force_flag && makerandom
like
it may have
it was
been
created by PGP
== 0 && legal_ctb
(ctb))
created by PGP. (y/N)?
"));
")
>
Zt
agkidessa\
pgp:coho */
nestflag
/*
= TRUE;
if (moreflag && makerandom == 0) “ls /* special name to cause printout on decrypt */ strcpy (literal_file_name, CONSOLE_FILENAME) ; literal_mode
= MODE_TEXT;
/* will
check
for
text
file
later
*/
else
if strcpy #ifdef
(literal_file_name,
file_tail
(inputfile));
MSDOS
strlwr
(literal_file_name) ;
#endif
} literal_file
/* to for
=
literal_file_name;
Make sure non-text files are not accidentally converted canonical text. This precaution should only be followed US
8-bit
ASCII
text
character
files,
codes
suitable for conversion text format. */ if
(literal_mode
==
since
and
European
still
to canonical
MODE_TEXT
&&
text
be legitimate
text
may
have
files
(CR/LF-terminated)
'!is_text_file
{
files
(workfile))
.
fprintf (pgpout, LANG ("\nNote: ’%s’ is not a pure text file.\n\ will be treated as binary data.\n"),
File
workfile); literal_mode
= MODE_BINARY;
/* now
expect
straight
binary
*/
i
if (moreflag && literal_mode == MODE_BINARY) { /* For eyes only? Can’t display binary file. */ fprintf (pgpout, LANG (""\n\007Error: Only text files may be sent as display-only.\n")); errorLvl
=
INVALID_FILE_ERROR;
user_error
();
aS*
See if plainfile looks like it might be incompressible, by examining its contents for compression headers for commonly-used compressed file formats like PKZIP, etc. Remember
whether
this
to
Naturally,
information
attempt
for
compression
later,
before
when
we
are
deciding
encryption.
don’t bother if we are making a separate signature or message. Also, don’t bother trying to compress a
clear-signed Hee He HHH
657
*/,
/*
658
* PGP
*/
.
message,
as
it’s
probably
/*
already
PGP
Source
Code
and
Internals
compressed.
*/ attempt_compression = compress_enabled && !separate_signature Inestflag && !clearfile && makerandom == 0 &&
file_compressible
(plainfile);
if (sign_flag) t if (!filter_mode && fprintf (pgpout, LANG
("\nA
if
secret
key
(!quietmode
&&
!quietmode)
is required
&& my_name[0]
to make
==
a signature.
"));
’\0’)
{ fprintf (pgpout, LANG ("\nYou specified no user ID to select your secret key,\n\ so the default user ID and key will be the most recently\n\ added
key on your
secret
keyring. \n"));
} strip_spaces clearfile
if
{
= FALSE;
= NULL;
(literal_mode
==
MODE_TEXT)
/* Text mode requires becoming canonical */ tempf = tempfile (TMP_WIPE | TMP_TMPDIR); /* +clear means output file with signature in the only in combination with -t and -a, not with if ('encrypt_flag && !separate_signature &&
emit_radix_64 clearfile
&& clear_signatures) = TRUE;
make_canonical (workfile, if (!clearfile)
rmtemp
clear, or -b */
= workfile;
strip_spaces
workfile
-e
tempf);
(workfile) ; =
tempf;
if (attempt_compression || encrypt_flag output_stdout) tempf = tempfile (TMP_WIPE | TMP_TMPDIR);
|| emit_radix_64 ||
else
tempf
= tempfile
(TMP_WIPE);
/* for
clear
status
= signfile
my_name,
workfile,
rmt emp workfile
signatures tempf,
we
(nestflag,
create
a separate
signature
separate_signature
literal_mode,
literal_file);
(workfile); = tempf;
ify (status = 0)
producing
“/s’. \n'").
++success;
} else
al
if (do_decrypt
(tempf)
>= 0)
++success;
rmtemp
(tempf);
as if
{
(!is_armor_file
if (!success) /* print decrypt anything */
(armorfile,
linepos))
error msg if we didn’t
user. error) (): return;
fprintf (pgpout, LANG ('"\nLooking for next
ls } /* do_armorfile
*/
/*
do_decrypt */ static
int
do_decrypt
(char *cipherfile)
{ char *outfile = NULL; intmstabuls eel boolean nested_info = FALSE;
char ringfile[MAX_PATH] ;
packet
in ’4%s’. ..\n''),
armorfile) ;
665
+/
/*
666
byte
*/
/*
PGP
Source
and
Internals
ctb;
byte header[8]; /* used to classify file type at the char preserved_name[MAX_PATH] ; char
Code
end.
*/
*newname;
/* will be set to the literal packet */
preserved_name[0]
original
file
name
after
processing
a
= ’\0’;
do
{ /* while nested parsable if (nested_info) rmtemp
(cipherfile);
cipherfile if
/* never
executed
(get_header_info_from_file
errorLvl
*/
on first
pass
*/
= outfile;
fprintf (pgpout, LANG ("\n\007Can’t return
info present
open
(cipherfile,
ciphertext
file
&ctb,
’%s’\n"),
1) < 0)
cipherfile);
= FILE_NOT_FOUND_ERROR;
-1;
} if
(!is_ctb
(ctb))
/* not
a real
CTB --
complain
*/
break;
if (moreflag) outfile = tempfile (TMP_WIPE else outfile = tempfile
/* PKE Ife
| TMP_TMPDIR);
(TMP_WIPE);
is Public
Key Encryption
(ss octbLetypes(ctb.
*/
CIBLPKE/TYPE) )
if (!quietmode) fprintf (pgpout, LANG ("\nFile is encrypted.
Secret
key is required
/* Decrypt to scratch file since we may have status = decryptfile (cipherfile, outfile); ta
a LITERAL2
(statism)
{ /* error
return
errorLvl = Tech abba ale
nested_info
else
if
=
*/
RSA_DECR_ERROR;
(status
> 0);
(is_ctb_type
(ctb,
CTB_SKE_TYPE) )
to read
*/
it.
"));
#7,
/*
File:
‘pgp.c’
= */
/*
if (decrypt_only_flag) { /* swap file names
instead
of just
copying the file
667
*/
*/
rmtemp (outfile) ; outfile = cipherfile; cipherfile = NULL;
if (!quietmode) fprintf (pgpout, LANG
("\nThis
file
nested_info
break;
=
has
a signature,
which
will
be left
in place.\n"));
FALSE;
/* Do no more
*/
} if (!quietmode) fprintf (pgpout, LANG ("\nFile has status
=
check_signaturefile
strip_sig_flag, it
signature.
} nested_info
=
if (strcmp
key is required
(cipherfile,
to check
signature.
outfile,
preserved_name) ;
ae(stacusm 0);
(preserved_name,
"/dev/null")
== 0)
rmtemp (outfile) ; fprintf (pgpout, "\n"); return
else
0;
if (is_ctb_type
(ctb,
CTB_CKE_TYPE) )
/* Conventional Key Encrypted ciphertext. */ /* Tell user it’s encrypted here, and prompt for
password in subroutine. */ if (!quietmode) fprintf (pgpout, LANG ("\nFile
is conventionally
/* Decrypt
it may be a LITERAL2
to
scratch
file
status = idea_decryptfile if (status < 0) { /* error return */ errorLvl
return nested_info
since
(cipherfile,
= DECR_ERROR;
-1; =
/* error (status
exit
> 0);
status
*/
outfile);
encrypted. */
"));
"));
/*
668
*/
else
/*
if (is_ctb_type
/* Compressed
text.
(ctb,
/* Always
Code
CTB_COMPRESSED_TYPE) )
(cipherfile,
outfile);
DECOMPRESS_ERROR;
assume
nested_info
Source
*/
status = decompress_file see ((GiRewne = 0)
status = maint_update (keyfile, 0); if (status == -7) { /* ringfile is a keyfile or secret keyring */
fprintf (pgpout, "Warning: ’%s’ keyfile); return
is not
a public keyring\n",
0;
} if
(status < 0) fprintf (pgpout,
LANG
("\OO07Maintenance
pass
error.
"));
/*
678
*/
/*
ite (sitbaciseo) id
fprintf
(pgpout,
errorLvl
LANG
("\007Key
signature
PGP
error.
Source
Code
and
Internals
"));
= KEY_SIGNATURE_ERROR;
} return
status;
} /* Key signing */ [|*#-- 3-3-9 -
*/
Casem
dus:
{ /*
*/
disable/revoke
Arguments:
userid,
if (myArge >= 4) strncpy (keyfile,
key
keyfile
myArgv[3],
sizeof
(keyfile)
- 1);
else
strcpy
(keyfile,
globalPubringName);
if (myArge >= 3) { strcpy (mcguffin,
myArgv[2]);
/* Userid
to sign */
else
{
fprintf (pgpout, LANG ("\nA user
disable.
ID is required
to select
the key you want
"));
fprintf (pgpout, LANG ("\nEnter user ID: ")); getstring (mcguffin, 255, TRUE); /* echo keyboard CONVERT_TO_CANONICAL_CHARSET status
= disable_key
(mcguffin);
(mcguffin,
if (status >= 0) « status = maint_update if (status == -7)
*/
keyfile);
(keyfile,
0);
{ /* ringfile is a keyfile or secret keyring */ fprintf (pgpout, keyfile); return
"Warning:
is not
a public keyring\n",
0;
ifs (statuss= 4) strncpy (ringfile, myArgv[3], sizeof (ringfile) else /* default key ring filename */ strcpy (ringfile, globalPubringName);
if (myArge
- 1);
>= 3)
if strcpy
(mcguffin,
myArgv[2]);
/* Userid
to edit
*/
else
{ fprintf LANG
(pgpout, ("\nA
user
ID
is required
to
select
the
key you
want
fprintf (pgpout, LANG ("\nEnter the key’s user ID: ")); getstring (mcguffin, 255, TRUE); /* echo keyboard */ CONVERT_TO_CANONICAL_CHARSET
status
= dokeyedit
if (status
x
(mcguffin);
(mcguffin,
ringfile);
>= 0)
status = maint_update (ringfile, 0); if (status == -7) status = 0; /* ignore "not a public keyring" if) (status < 0) fprintf (pgpout, LANG ("\007Maintenance pass
ifeCstbavuse< {
fprintf
error error.
*/ "));
0)
(pgpout,
errorLvl
=
LANG
("\007Keyring
edit
error.
"));
KEYRING_EDIT_ERROR;
S return
status;
} /* Key edit
*/
[ rn caselwas:
{ /*
Add key to key ring
Arguments:
+/
if (myArge
keyfile,
< 3 &&
ang werror)()?
ringfile
!filter_mode)
*/
to
edit.
"));
679
*/
/*
680
*/
/*
if (!filter_mode) { /* Get the keyfile from args */ strncpy (keyfile, myArgv[2], sizeof
PGP
(keyfile)
- 1);
#ifdef MSDOS strlwr (keyfile); #endif
if (!file_exists
(keyfile))
default_extension
if (!file_exists { fprintf (pgpout, LANG
('"'\n\007Key
(keyfile,
PGP_EXTENSION) ;
(keyfile))
file
’%s’
does
not
exist.\n"),
keyfile); errorLvl = return -1;
NONEXIST_KEY_ERROR;
workfile
= keyfile;
workfile
= tempfile
else
"f readPhantomInput
(TMP_WIPE
| TMP_TMPDIR) ;
(workfile) ;
if (myArge < (filter_mode
7? 3 : 4))
{ /* default key ring filename byte
*/
ctb;
get_header_info_from_file
if
(ctb
strcpy
==
(workfile,
&ctb,
1);
CTB_CERT_SECKEY)
(ringfile,
globalSecringName) ;
(ringfile,
globalPubringName);
else
strcpy else
{ strncpy
(ringfile,
myArgv[(filter_mode
sizeof (ringfile) - 1); default_extension (ringfile, #ifdef
MSDOS
strlwr
(ringfile);
#endif status if
= addto_keyring
(filter_mode)
(workfile,
? 2 : 3)],
PGP_EXTENSION) ;
ringfile);
Source
Code
and
Internals
*/
;®
SsEWMessa
rmtemp if
pepect in +7
681
(workfile);
(status
< 0)
fprintf
(pgpout,
errorLvl return
/*
=
LANG
("\007Keyring
add
error.
"));
KEYRING_ADD_ERROR;
status;
} /* Add key to key ring */ /*------------------------------------------------------- */
case
’x’
{ /*
Extract
poe tgs
mcguffin,
key from key ring keyfile,
ringfile
*
if (myArge >= (filter_mode ? 4 : 5)) /* default key ring filename */ strncpy (ringfile, myArgv[(filter_mode ? 3 : 4)], sizeot (ringfile) — 1); else
strcpy
(ringfile,
if (myArge al
>=
globalPubringName) ;
(filter_mode
? 2 : 3))
if (myArgv[2])
/* Userid to extract */ strcpy (mcguffin, myArgv[2]);
else
Strcepyancgut fing. "))s else
{
fprintf
(pgpout,
LANG ("\nA user ID is required to if (batchmode) /* not interactive,
must
be
on
returns
fprintf
getstring
command
line
(pgpout,
LANG
(mcguffin,
if (!filter_mode) A if (myArge >= 4) strncpy (keyfile, else
keyfile[0] workfile
the
key
you
want
*/
—1
("\nEnter
255,
CONVERT_TO_CANONICAL_CHARSET
}
select userid
=
’\0’;
= keyfile;
TRUE);
the key’s user
ID:
"));
/* echo keyboard */
(mcguffin);
myArgv[3],
sizeof
(keyfile)
- 1);
to
extract.
"));
#/;
PGP Source
/*
*/
682
/*
Code
and
Internals
else
{ workfile
= tempfile
(TMP_WIPE
| TMP_TMPDIR);
} #ifdef
MSDOS
strlwr strlwr
(workfile) ; (ringfile);
#Hendif
default_extension
status
(ringfile,
PGP_EXTENSION) ;
= extract_from_keyring
ringfile,
(filter_mode
(mcguffin,
? FALSE
workfile,
:
emit_radix_64));
rae (iesyane! < )) { fprintf (pgpout, errorLvl
if
LANG
("\007Keyring
extract
error.
"));
= KEYRING_EXTRACT_ERROR;
(filter_mode) rmtemp (workfile) ;
return
status;
} if
(filter_mode if
!status)
(emit_radix_64)
/* NULL for if
&&
outputfile means
(armor_file
(workfile,
write
NULL,
to stdout
NULL,
NULL)
*/ != 0)
{ errorLvl = return -1;
UNKNOWN_FILE_ERROR;
i } else
if
{ (writePhantomOutput errorLvl return
(workfile)
< 0)
= UNKNOWN_FILE_ERROR;
-1;
i rmtemp return
(workfile);
0;
} /* Extract
{ /*
key from key ring */
Remove
keys
or
selected
key
signatures
from
userid
keys
*/
ye
BEULeCIAL
pep:God */
Arguments:
userid,
/*
ringfile
*/ if (myArge >= 4) : strcpy (ringfile, myArgv[3]); else /* default key ring filename */ strcpy (ringfile, globalPubringName) ; if (myArge
>= 3)
j strcpy
(mcguffin,
myArgv[2]);
/* Userid to work on */
else
easen
tle)
fprintf (pgpout, LANG ("\nA user ID is required to select remove certifying signatures from. "));
the public key you want
to\n\
else
{ fprintf (pgpout, LANG ("\nA user } if
ID is required to select
(batchmode)
command
line
return
/* not
interactive,
the key you want
userid
must
to remove.
be on
*/
-1;
fprintf (pgpout, LANG ("\nEnter the key’s user ID: ")); getstring (mcguffin, 255, TRUE); /* echo keyboard */ CONVERT_TO_CANONICAL_CHARSET #ifdef strlwr #endif
(mcguffin);
MSDOS (ringfile) ;
if (!file_exists
(ringfile))
default_extension
if (sign_flag)
{ /* Remove if
(ringfile,
signatures
(remove_sigs
PGP_EXTENSION) ;
*/
(mcguffin,
ringfile)
< 0)
4. fprintf
(pgpout,
errorLvl return
LANG
("\007Key
signature
remove
error.
= KEYSIG_REMOVE_ERROR ;
-1;
i else
{ /* Remove keyring if
*/
(remove_from_keyring
(boolean)
(myArge
< 4))
(NULL,
< 0)
mcguffin,
ringfile,
"));
"));
683
*/
/*
684
fprintf
*/
/*
(pgpout,
errorLvl = return -1;
LANG
("\007Keyring
remove
PGP
error.
Source
Code
"));
KEYRING_REMOVE_ERROR;
} return
0;
} /* remove
key signatures
case ’V’?: /* -kvv */ { /* View or remove with userid match Arguments: userid,
from userid
*/
key ring entries,
ringfile
*/ if (myArge < 4) /* default
key ring filename
strcpy else
(ringfile,
globalPubringName) ;
strcpy
(ringfile,
myArgv[3]);
*/
if (myArge > 2) { strcpy (mcguffin, myArgv[2]); if (strcmp (mcguffin, "*") == mcguffin[0] = ’\0’; else
{ *mcguffin
=
’\0’;
if ((myArge == 3) && has_extension { strcpy (ringfile, myArgv[2]);
mcguffin[0]
(myArgv[2],
PGP_EXTENSION) )
= ’\0’;
ap CONVERT_TO_CANONICAL_CHARSET #ifdef
MSDOS
strlwr
(ringfile);
(mcguffin);
#endif
if (!file_exists
(ringfile) )
default_extension
/* If a second status
’v’
(ringfile,
(keychar = V), show signatures
= view_keyring
(mcguffin,
(boolean) (keychar == if (status < 0)
fprintf
(pgpout,
PGP_EXTENSION) ;
LANG
’V’),
too */
ringfile,
c_flag);
("\007Keyring view error.
"));
and
Internals
oy
[ee
ileretatpgpwc:hhor#/
errorLvl return
/*
= KEYRING_VIEW_ERROR;
status;
f
} /* view
key ring
entries,
with
userid
match
*/
default:
arg_error return
();
0;
} /* do_keyopt
*/
/* Wisseug_ Sicac@c */
/* comes
here
es
if user
made
a boo-boo.
*/
void
user_error
fprintf fprintf
s;
()
(pgpout, (pgpout,
LANG
("\nFor a usage
summary,
type:
pgp —-h\n"));
LANG ("'For more detailed help, consult the PGP User’s exitPGP (errorLvl ? errorLvl : 127); /* error exit */
#if
defined(DEBUG)
#include #endif
&&
Guide. \n"));
defined(linux)
/* * exitPGP: wipes * the stack.
and removes
temporary
files,
also
tries
to wipe
*/ /*
exitPGP */ void
exitPGP
ai
(int
returnval)
char buf [STACK_WIPE] ; struct
hashedpw
*hpw;
if (verbose) fprintf (pgpout, "exitPGP: exitcode = %d\n", for (hpw = passwds; hpw; hpw = hpw->next) memset (hpw->hash, 0, sizeof (hpw->hash)); for (hpw = keypasswds; hpw; hpw = hpw->next) memset
(hpw->hash,
cleanup_tmpf
();
/* Merge
entropy
any
if (cryptRandOpen
0,
sizeof
we
collected
((struct
returnval) ;
(hpw->hash) ); into
the
IdeaCfbContext
randseed.bin
*) 0) >= 0)
file
*/
685
*/
/*
686
*/
/*
cryptRandSave ((struct IdeaCfbContext #if defined(DEBUG) && defined(linux) if (verbose)
PGP
Source
Code
and
*) 0);
{ struct
mstats
mstate=
mstat;
mstats
printf
©);
('%d chunks
mstat.chunks_used,
used
(%d bytes)
‘%d bytes
mstat.bytes_used,
total\n",
mstat.bytes_total) ;
} #endif memset #ifdef /*
* Fake
(buf,
0, sizeof
(buf));
/* wipe
stack
*/
VMS
VMS
style
error
returns
with
severity
in bottom
3 bits
*/ if
(returnval) returnval = (returnval
> 24;
pliir=+t
>>-16;
pl2]
=+t
>>
p[3]
= t;
p t=
4;
8;
i++)
721
Ve)
22)
/* Set
7,
/*
up pointers
for
future
randPoolAddPos
=
randPoolGetPos
= sizeof
addition
PGP
or removal
Source
Code
of random
and
bytes
Internals
*/
0;
(randPoolKey);
i /* * Make a deposit of information (entropy) into the pool. The bits * deposited need not have any particular distribution; the stirring * operation transformes them to uniformly-distributed bits.
=m) /*
randPoolAddBytes */ void
randPoolAddBytes
(byte const
*buf,
unsigned len)
{ unsigned
t;
while (len > (t = sizeof (randPool) - randPoolAddPos)) { xorbytes ((byte *) randPool + randPoolAddPos, buf, t); bute. len -= t;
randPoolStir
();
3s if
(len)
{ xorbytes
((byte
*) randPool
randPoolAddPos
+=
randPoolGetPos
= sizeof
+ randPoolAddPos,
buf,
len);
len;
(randPool);
/* Force
stir
on
get
*/
} /* * Withdraw some bits from the pool. Regardless of the distribution of the * input bits, the bits returned are uniformly distributed, although they * cannot, of course, contain more Shannon entropy than the input bits.
y/
/*
randPoolGetBytes +/ void randPoolGetBytes
{
unsigned while
(byte
* buf,
unsigned
len)
t;
(len > (t = sizeof
(randPool)
- randPoolGetPos) )
t memcpy
(buf,
(byte
*) randPool
+ randPoolGetPos,
t);
*/
/*
File:
buf len
‘randpool.c’
+= -=
¥*/
1s
t; t;
randPoolStir
();
i; if
(len)
S memcpy
(buf,
(byte *) randPool
randPoolGetPos
+=
+ randPoolGetPos,
len;
} } /*
randPoolGetByte */ byte
randPoolGetByte
(void)
{ if
(randPoolGetPos randPoolStir ();
return
(((byte
==
sizeof
(randPool))
*) randPool) [randPoolGetPos++] ) ;
len);
Pies
37,
/*
724
*/
/*
/* File: /* (New File)
‘rsagen.h’
Source
Code
and
Internals
*/
*/
rsagen.h
/*
PGP
(c) Copyright
- C include
file
for RSA public-key
1987 by Philip Zimmermann.
key generation
routines.
All rights reserved.
The author assumes no liability for damages resulting from the use of this software, even if the damage results from defects in this software. No warranty is expressed or implied. RSA-specific routines follow. These are the only functions that are specific to the RSA public key cryptosystem. The other multiprecision integer math functions may be used for non-RSA applications. Without these functions that follow, the rest of the software cannot perform the RSA public key algorithm.
ca
NOTE:
This
assumes
previous
inclusion
of
"mpilib.h"
int rsa_keygen (unitptr n, unitptr e, unitptr d, unitptr p, unitptr q, unitptr u, short keybits, /* Generate
RSA
key
components
p,
q,
n,
e,
d,
and
short u.
*/
and
"genprime.h"
ebits);
*/
Ye
eEitextnYrsagensc?
/* File:
*/
*/
rsagen.c version
First
/*
‘rsagen.c’
/* (New File) /*
»o%/
— C source 17 Mar 87
(c) Copyright
code
for
RSA
public-key
1987 by Philip Zimmermann.
key generation
routines.
All rights reserved.
The author assumes no liability for damages resulting from the use of this software, even if the damage results from defects in this software. No warranty is expressed or implied. RSA-specific routines follow. These are the only functions that are specific to the RSA public key cryptosystem. The other multiprecision integer math functions may be used for non-RSA applications. Without these functions that follow, the rest of the software cannot perform the RSA public key algorithm. The
RSA
public
Institute
not
of
key
cryptosystem
Technology
apply outside
(U.S.
the USA.
is patented
patent
Public
by the
#4,405,829).
Key Partners
Massachusetts This
(PKP)
patent
holds
does
the
exclusive commercial license to sell and sub-license the RSA public key cryptosystem. The author of this software implementation of the RSA algorithm is providing this software for educational use only. Licensing this algorithm from PKP is the responsibility of you, the user, not Philip Zimmermann, the author of this software. The author assumes no liability for any breach of patent law resulting from the unlicensed use of this software by the user.
+/ #include #include #include #include #include
"mpilib.h" "genprime.h"' "rsagen.h"' "random.h" "rsaglue.h"
static void derive_rsakeys (unitptr n, unitptr e, unitptr d, unitptr p, unitptr q, unitptr u, short ebits); /* Given primes p and q, derive RSA key components n, e, d, and u.
/* Define
some
error
#define
KEYFAILED
#define
swap(p,q)
status
returns
-15 /* key failed
for
RSA
keygen...
final test
{ unitptr t; t =p;
p=q;
*/
*/
q=t;
}
*/
725
+/
Code and Internals
PGP Source
/*
*/
726
/*
/*
derive_rsakeys +/ static
void
derive_rsakeys
(unitptr n, unitptr
e, unitptr d,
unitptr p, unitptr q, unitptr u, short ebits) /* * Given primes p and q, derive RSA key components * The global_precision must have already been set * * * * * *
n, e, d, and wu. large enough for n.
Note that p must be < q. Primes p and q must have been previously generated elsewhere. The bit precision of e will be >= ebits. The search for a usable exponent e will begin with an ebits-sized number. The recommended value for ebits is 5, for efficiency’s sake. This could yield an e as small as 17.
{
unit F[MAX_UNIT_PRECISION] ; unitptr ptemp, qtemp, phi, G; /* scratchpads /*
*/
For strong prime which the modulus may It must be big enough goodprime reasonably
#define
latitude(bits)
*/
generation only, latitude is the amount differ from the desired bit precision. to allow primes to be generated by fast.
(max(min(bits/16,12),4))
/* between
4 and
12 bits
ptemp = d; /* use d for temporary scratchpad array */ qtemp = u; /* use u for temporary scratchpad array */ phi =n; /* use n for temporary scratchpad array */ G = F;
/* use
F for
if (mp_compare swap /*
both
G and
F */
(p, q) >= 0) /* ensure
(p, q); /* swap phi(n)
is
the
the pointers Euler
totient
that p 12) /* G shouldn’t get really big. mp_display ("\007G =", G); /* Worry the user. */ #Hendif
¥*/
*/
/* DEBUG
*/
*/
is
2.
of
*/
*/
Paves?
/*
mp -udiv mp _move
ei rsagentic?
#o'%/
(ptemp, qtemp, (F, qtemp);
fe
phi,
G); /* F(n)
= phi(n)/G(n)
¥*/
Pw
We
now
have
phi
and
F.
Next,
compute
e...
Strictly speaking, we might get slightly faster results by testing all small prime e’s greater than 2 until we hit a good e. But we can do just about as well by testing all odd e’s greater than 2. We could begin searching for a candidate e anywhere, perhaps using a random 16-bit starting point value for e, or even larger values. But the most efficient value for e would be 3, if it satisfied the gcd test with phi. Parameter ebits specifies the number of significant bits e should have to begin search for a workable e. We OE TE 96 oe ee Te ee i Make e at least 2 bits long, and no longer than one bit * shorter than the length of phi. *
/
ebits = min if (ebits == ebits = 5; ebits = max
mp_init
(ebits, countbits (phi) - 1); 0) /* default is 5 bits long */ (ebits, 2);
(e, 0);
mp_setbit (e, ebits - 1); lsunit (e) |= 1; /* set e candidate’s mp_dec (e);
mp_dec
(e);
/* precompensate
lsb
- make
for preincrements
it odd
*/
of e */
do
{ mp_inc mp_inc
(e); (e);
mp_gcd
(ptemp,
gced(e,phi(n)) while
(testne Now
/*
we
/* try odd e’s until e,
phi);
(ptemp,
(d,
e,
e such
*/ that
have
e.
1)); Next,
compute
inverse inverse p*q.
/
mp_inv
we get it. for
= 1 */
d is the multiplicative u is the multiplicative n is the public modulus *
/* look
F);
/* compute
d such
d,
then
u,
then
n.
of e, mod F(n). of p, mod q, if p= 0) { /* ensure that pp.
*/
for computing u */ mp_move
mp_move mp_move
(u, p);
(p, q); (q, wu);
/* See
mp_move
mp_sub
if p and
q are
far
enough
apart.
(u, q); /* use u as scratchpad
(u, p); /* compute q-p */
too_close_together
/* Keep trying
=
(countbits
q’s until
(u)
we get one
Is q-p big enough?
*/
< (countbits
far
enough
(q) - 7));
from p...
*/
*/
729
*/
/*
730
*/
while
/*
derive_rsakeys /* Now
test
unit
Code
and
Internals
(n,
e, d, p,
q, u,
(); /* ensure
ebits);
recycled random pool
key just to make
sure
--this
is destroyed
had better
work!
*/
*/
C[MAX_UNIT_PRECISION] ; obS
/* Create for
Source
(too_close_together) ;
trueRandFlush
bake
PGP
a dummy signature */ (i = 0;
i < 16;
itt)
CCbytes* eC) Filo= Ses eiire?; /* Encrypt it */ status
if
= rsa_private_encrypt
(status return
/* Extract status
if
< 0) /* modexp
status;
/*
return
the signature
return
< 0) /* modexp
status;
/*
(statisim! return
steps
*) C,
16,
e, d, p,
q, u, n);
*/
error
*) C, C,
e, n);
*/ status
same thing back.
*/
*/
a6)
KEYFAILED;
(GL S fe
al < lee
sinks),
if (((byte *) C)[iJ return
status
((byte
error?
return
/* Verify that we got the af
error
(byte
*/
*/
= rsa_public_decrypt
(status
(C,
error?
!= 3 * i + 7)
KEYFAILED;
a return 0; /* normal } /* rsa_keygen */ oboe em:
return
End
*/
of RSA-specific
routines
se
/
*/
/*
File:
‘rsaglue.h’
: /* File:
¢
*/
7%
‘rsaglue.h’
/* (New File) */ /* rsaglue.h extern
char
|
- Glue
routines
signon_legalese[]
/* Declarations
*/
for RSA
encryption
and decryption
*/
;
*/
int rsa_public_encrypt (unitptr outbuf, byteptr inbuf, short bytes, unitptr E, unitptr N); int rsa_private_encrypt (unitptr outbuf, byteptr inbuf, short bytes, unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr int rsa_public_decrypt (byteptr outbuf, unitptr inbuf,
unitptr E, unitptr int rsa_private_decrypt unitptr
E,
N);
(byteptr
unitptr
N);
D,
outbuf,
unitptr
unitptr P,
unitptr
inbuf, Q, unitptr
U,
unitptr
N);
Sst
*/
/*
732
#/
/*
/* File: /*
‘rsagluet.c’
PGP
Source
Code
and
Internals
*/
(New File) */
SS*
rsagluei.c
data
- These
functions
encryption keys
(DEKs)
wrap
and unwrap
message
digests
in padding and RSA-encrypt
them
(MDs)
and
into
multi-precision integers. This layer of abstraction was introduced to allow the transparent use of either the RSAREF Cryptographic Toolkit from RSA Data Security Inc for the RSA calculations (where the RSA patent applies), or, Philip Zimmermann’s mpi library for the RSA calculations. The rsaglue.c module from PGP version 2.3a performs the same functions as this module, but can be compiled to select the use of mpilib functions instead of RSAREF as the underlying math engine. That version of rsaglue.c would be suitable where the RSA patent does not apply, such as Canada. This file uses MPILIB to perform the actual encryption and decryption. It uses the same PKCS format as RSAREF, although it also accepts an older format used in PGP 2.1.
(c) Copyright
1990-1994
by Philip Zimmermann.
All rights reserved.
The author assumes no liability for damages resulting from the use of this software, even if the damage results from defects in this software. No warranty is expressed or implied. Note that while most PGP source modules bear Philip Zimmermann’s copyright notice, many of them have been revised or entirely written by contributors who frequently failed to put their names in their code. Code that has been incorporated into PGP from other authors was either originally published in the public domain or is used with permission from the various authors. PGP
is available
See the
important HEHE HEHEHE HEHE HE KH HH HHH HHHH certain
2;
if (i > nndigits) i = nndigits; nndigits -= i; #ifdef
HIGHFIRST
p = (word32
*) (mpi + global_precision) ;
0);
749
*/
/*
750
while
*/
/*
PGP
Source
Code
and
Internals
(i--)
saqiness
ES
L385
#else
p = (word32
*) mpi;
while (i--) *nnt+ = *pt+; #Hendif
while
(nndigits-—)
*nnt++
= 0;
i /*
NN_ModExp */ void NN_ModExp word32
unit unit alae
(word32 * result, word32 * base, * modulus, unsigned moddigits)
Sie
oldprecision;
oldprecision
set_precision
= global_precision;
(MAX_UNIT_PRECISION) ;
nn2mpi
(b, base,
nn2mpi
(c, exponent,
nn2mpi
(d, modulus,
moddigits);
expdigits) ; moddigits);
i = mp_modexp (a, b, c, d); ayasciaa (al SS @))s mpi2nn (result, moddigits, a);
set_precision te ndif
* exponent,
a[MAX_UNIT_PRECISION] , b[MAX_UNIT_PRECISION] ; c[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION] ;
unsigned
}
word32
(oldprecision) ;
unsigned
expdigits,
*/
/*
File:
‘sleep.c’
/* File: /* (New File)
*/
/*
‘sleepyc?
*/
*/
[FREER * sleep.c -- provide
unix
style
sleep
function
*
AR A / #include /*
sleep */ int
sleep
(unsigned
long long
start; check;
long
finish;
secs)
time (&start); finish = start
+ (long) secs; #ifdef DEBUG printf ("sleep for 4d secs, stop time (&check); printf #endif
for
{
("it
is now
%ld\n",
eGys) time (&check); if (check > finish)
break;
return
I
(0);
sleeping
check);
at %ld\n",
secs,
finish);
761
#
/*
752
/*
*/
/*
Patlemmistdlvb,hh? */
/* (New File)
*/
/*
* Fake
+7,
stdlib.h
#Hinclude #ifndef
aAtolm@)s
extern
old
NULL
#define NULL #endif char *getenv char *malloc char *calloc char *realloc
long
for
int
( char *)0 () ’. () ’. 0) ,. ( ) .’
errno;
systems
PGP
Source
Code
and
Internals
*/
/*
File:
‘system.h’
/* File:
© */
/*
‘system.h’
*/
/* (New File) */ #ifndef #define
SYSTEM_H SYSTEM_H
#ifdef UNIX #if !defined(HAVE_UNISTD_H) #define HAVE_UNISTD_H #tHendif
&&
!defined(MACH)
&&
!defined(_BSD)
#ifdef HAVE_UNISTD_H #include #else
#include
#include
#Hendif
int getch
int kbhit
();
();
/* replacement
function for obsolete
#endif
*/
long Clock (); /* UNIX
#if defined(UNIX) void
ttycbreak
void ttynorm
|| defined(AMIGA)
clock(),
|| defined(VMS)
();
();
#else
#define #define
ttycbreak() /* nothing */ ttynorm() /* nothing */
#endif #if
'defined(MSDOS)
char
*strlwr
(char
&&
*);
#Hendif
void
breakHandler
#endif
/* SYSTEM_H
(int);
*/
just provides random data */
!defined(ATARI)
753
*/
/*
754
+*/
/*
/* File: /* (New File)
‘system.c’
PGP
Source
Code
and
Internals
*/
*/
aS*
system.c
Routines
specific
for non-MSDOS
implementations
of pgp.
(c) Copyright 1990-1994 by Philip Zimmermann. All rights reserved. The author assumes no liability for damages resulting from the use of this software, even if the damage results from defects in this software. No warranty is expressed or implied. Note that while most PGP source modules bear Philip Zimmermann’s copyright notice, many of them have been revised or entirely written by contributors who frequently failed to put their names in their code. Code that has been incorporated into PGP from other authors was either originally published in the public domain or is used with permission from the various authors. PGP is available for free to the public under certain restrictions. See the PGP User’s Guide (included in the release package) for important information about licensing, patent restrictions on certain
algorithms,
trademarks,
copyrights,
and
export
controls.
Modified 24-Jun-92 HAJK Adapt for VAX/VMS. Modified: 11-Nov-92 HAJK Add FDL Support Routines.
Modified: 31-Jan-93 HAJK Misc. updates for terminal Add VMS command stuff. Add fileparse routine.
HEHEHE HEHE HEH OE HH HH HHH
handling.
*/ #include #include #include #include
"“exitpgp.h" "system.h" "usuals.h"
*/ #if def
UNIX
/* *
* *
Define USE_SELECT to use the select() system call to check if keyboard input is available. Define USE_NBIO to use non-blocking read(). If you don’t define anything the FIONREAD ioctl() command
*/
/*
File:
* will
‘system.c’
be
*/
/*
755
used.
*
* Define
NOTERMIO
*/
if you
#include
#include
don’t
have
the
termios
stuff
#ifndef NOTERMIO #ifndef SVR2 #include #else #include
#endif
/* not SVR2 */
#else
#include
#Hendif
#ifdef
USE_SELECT
#include #ifdef
_IBMR2
#include
#endif /* _IBMR2 #else #ifndef USE_NBIO #ifndef sun
#include
*/
/* for FIONREAD
#else /* including both #include #endif /* sun */ #ifndef #define #endif #endif #endif
FIONREAD FIONREAD
#include
static static static
ioctl.h
TIOCINQ
void setsigs (void); void rmsigs (void); void sigi (int);
static void sig2 (int); void breakHandler (int); static) int-ttyid-= -1; #ifndef SVR2 static void (*savesig) (int); #else
static
int
(*savesig)
#endif
void ttycbreak
void ttynorm
(void);
(void);
(int);
*/
and termios.h
gives
a lot of warnings
on sun */
*/
/*
756
#ifndef #undef #endif
*/
/*
PGP
Source
Code
and
NEED_KBHIT USE_NBIO
#ifndef NOTERMIO #ifndef SVR2 static struct termios itio, tio; #else static struct termio itio, tio;
#endif
/* not
SVR2
+/
struct
sgttyb
#else
static
isg,
sg;
#endif
#ifdef static static
USE_NBIO int kbuf = -1; int fflags;
/* buffer
to
store
char
read
O_RDWR))
< 0)
by kbhit()
*/
#endif static
int gottio
= 0;
/*
ttycbreak */
void
ttycbreak {
(void)
if (ttyfd
== -1)
{ if
((ttyfd = open
fprintf (stderr, ttyfd = 0;
("/dev/tty",
"cannot
open tty,
using
stdin\n");
} #ifndef #ifndef
NOTERMIO SVR2
if (tcgetattr
(ttyfd,
&tio)
< 0)
#telse
ifscioctl
#endif {
(ttyid,
ICGETA,
&til0)
fprintf (stderr, "\nUnable perror ('tocti") exitPGP
(1);
itio = tio; setsigs (); gottio = 1; #ifdef
_kbhitChan_ IOSB
=
0;
");
/*
Prompt
string
*/
Internals
*/
/*
File:
‘system.c’
unsigned unsigned unsigned unsigned
}
short short short short
*/
/*
765
sts; byteCount; terminator; terminatorSize;
iosb; static
$DESCRIPTOR
static
volatile
char
(kbdev_desc,
"SYS$COMMAND:");
struct
Class;
char Type; unsigned short BufferSize; unsigned int Mode; int
}
ExtChar;
CharBuf,
OldCharBuf;
static $DESCRIPTOR File Descr */
(out_file_descr,
static
FDL$M_FDL_STRING;
int
flags
=
**-kbhit_handler-This
exit
"SYS$DISK:[]");
handler
restores
the
/* Default
terminal
Output
characteristics
Description: This procedure is invoked to return the the terminal to normality on what you think is normal!). Anyway, it gets called to restore characteristics either through ttynorm or via an exit handler.
*/
/*
po
enenalen
*
static
void
kbhit_handler
ttynorm (void)
(int
*sts)
();
sys$dassgn
_kbhitChan_) ;
_kbhitChan_
(
= 0;
} /* * Data
*/
Structures
unsigned static
int
struct
exsts;
For Linking
Up Exit
Handler
(depends
7,
766
*/
/*
PGP Source
Code
and
Internals
Sen GaelKee VOID *rtn; int argcnt; int *stsaddr;
a exhblk
=
0, &(kbhit_handler),
1, &(exsts)
. ’
—*
**-kbhit_Getchn-Get Functional
Channel
Description:
Private routine to get characteristics.
a terminal
channel
and save
the terminal
Arguments: None. Returns:
If 0, channel already assigned. If odd, otherwise returns VMS error status. Implicit
Channel
Initial Channel
ee ee ee ee 2 ee ee RE Oe ~S*
Spit ag setulae *
So AtCu lint kb hit_Getchn
()
t if
successful
assigned to the terminal
(if any).
terminal assigned
characteristics. to the terminal.
Effects:
Establishes an exit terminal channel.
he
was
Outputs:
OldCharBuf _kbhitChan_ Side
assign
Inputs:
_kbhitChan_ Implicit
then
SES
= Og
(_kbhitChan_
==
0)
handler
to
restore
characteristics
and
deassign
*/
/*
File:
‘system.c’
if ((sts
¥*/
= sys$assign
/*
(
&kbdev_desc, &_kbhitChan_,
0,
0)) & 1)
{
if ((sts
= sys$qiow
(
0, _kbhitChan_, I0$_SENSEMODE, &iosb, 0,
0, &01ldCharBuf,
Te
0, 0, 0, 0))
& 01) sts = iosb.sts; sae (Ghee €2 Oil) if
(!(OldCharBuf.Class
& DC$_TERM) )
of fprintf exitPGP
(stderr, (1);
(void)
return
"\nNot
sys$dclexh
running
on
a terminal");
(&exhblk);
(sts);
}
/* * **k-ttynorm-Restore
initial
terminal
characteristics
*
* Functional
Description:
*
* This
procedure
*/ /*
ttynorm */ void
ttynorm
()
/* * Arguments: *
*
None.
is
invoked
to restore
the
initial
terminal
characteristics.
767
*/
768
Ss*
+/
/*
PGP
Source
Code
and
Internals
*
* Implicit
Inputs:
*
* *
QOldCharBuf _kbhitChan_
Initial Channel
terminal assigned
characteristics. to the terminal.
*
* Implicit
Outputs:
*
*
None.
Al ‘l int
if
sts;
(_kbhitChan_
!= 0)
1 CharBuf.Mode
=
OldCharBuf.Mode;
CharBuf.ExtChar
=
OldCharBuf.ExtChar;
/*
CharBuf.Mode &= ~TT$M_NOECHO; CharBuf.ExtChar &= ~TT2$M_PASTHRU;
*/ if ((sts
= sys$qiow
(
0, _kbhitChan_, I0$_SETMODE, &iosb,
0,
0,
&OldCharBuf ,
sts
=
iosb.sts;
ifuGi(sts
at
&101))
fprintf (stderr, "\nFailed (void) lib$signal (sts);
5
to reset
terminal
characteristics!");
} return;
a; /* * **-kbhit-Find
out
if a key has
been
pressed
*
* Description: *
* Make the terminal noecho and sense * the typeahead count. Note that the
the characters coming in by looking at character remains in the typeahead buffer
/*
File:
‘system.c’
* untill * mode.
either
¥*/
read,
or that
/*
the
user
types
a Control-X
* Arguments: None. Returns:
TRUE FALSE
if there if there
is a character in the typeahead buffer. is no character in the typeahead buffer.
Intescse struct
ef unsigned
short
TypAhdCnt ;
char
FirstChar;
char
Reserved[5];
} TypCharBuf ;
/* **x
Get
typeahead
*/
if ((sts = sys$qiow
count
(
0,
_kbhitChan_, IO$_SENSEMODE
| IO$M_TYPEAHDCNT,
&iosb,
0, O,
&TypCharBuf ,
8, 0, 0, 0, 0))
& 01) sts =
iosb.sts;
if (sts & 01)
return (TypCharBuf.TypAhdCnt (void) lib$signal (sts);
exitPGP
(1);
> 0);
when
not
in
769
’passall’
*/
/*
WerO!
static {0,
ef,
/*
int NoTerm[2]
0};
/*
Source
Code
and
Internals
=
TT Terminator
**-getch-Get
PGP
Mask
a character
(Nothing)
and return
*/
it
Description: Get
a character
from
will be explicitly character
is
the
keyboard
echoed unless
in the
typeahead,
and
return
ttycbreak()
that
will
it.
be read
* Arguments: None. Returns: ag Hap san Gar Go
A
Character
Read.
* =
unsigned
int
volatile
char
if (((ste
sts; CharBuf;
= kbhit_Getchn
if ((sts = sys$qiow 0, _kbhitChan_, IO$_READVBLK , &iosb,
0, 0, &CharBuf ,
1, 0, &NoTerm,
0 )) & 01) sts
i
iosb.sts;
if (sts & 01)
()) & 01)
(
Unlike
has been
|| sts == 0)
first.
Unix,
called
the
first.
character
If the
*/
/*
File:
‘system.c’
*/
/*
return ((int) CharBuf); fprintf (stderr, "\nFailed (void) lib$signal (sts);
to
get
character");
} **-putch-Put
*
Character
To
’Console’
Device
*
* This procedure is a companion to getch, outputing a character to the * terminal with a minimum of fuss (no VAXCRTLK, no RMS!). This routine * simply gets a channel (if there isn’t one already and uses QIO to * output. *
putch */ int
putch
(int
chr)
/*
Arguments: chr
*
Character
to
output.
Returns:
Status Side
return
Getchn
and
qio.
Effects
& eh +eeeeeeue May assign a
{
from
channel
to the
terminal.
*/ unsigned
int
sts;
if (((sts = kbhit_Getchn if ((sts
= sys$qiow
0, _kbhitChan_, IO$_WRITEVBLK, &iosb,
)) & 01) iosb.sts;
()) & 01) (
|| sts == 0)
771
*/
/*
¥/
FTTD
Te
PGP Source
Code
and Internals
Ny if
(stse&201) return (sts); fprintf (stderr, "\nFailed (void) lib$signal (sts);
to put
character");
2 /*
* *k-ttycbreak-Set
Unix-like
Cbreak
mode
*
* Functional
Description:
*
* This code must * disables echo,
be invoked to produce the Unix-like allows control character input.
cbreak
*/ /*
ttycbreak */ void
ttycbreak
()
/*
* Arguments: None. Returns:
None.
Side
Effects
May assign
a channel
to the
terminal.
HEHE HF HK HE eee Ss
if
struct
unsigned
short
TypAhdCnt ;
char
FirstChar;
char
Reserved[5];
sy TypCharBuf; char buf[80]; SIH. BESS
ao
—skbhitmGetchnm
/* * Flush
#7,
any
typeahead
if ((sts
©)
before
= sys$qiow
(
mcm Ol)
we
mllmstsm——m0))
change
characteristics
operation
which
*/
/*
File:
‘system.c’
0, _kbhitChan_, IO$_SENSEMODE
+*/
/*
; | IO$M_TYPEAHDCNT,
&iosb,
0,
0,
&TypCharBuf,
8, >
0> 0) 0 )) sts
=
& 01)
iosb.sts;
if
(sts)
{ if (TypCharBuf.TypAhdCnt > 0) af if ((sts = sys$qiow ( 0, _kbhitChan_, IO$_READVBLK &iosb,
| IO$M_NOECHO
| IO$M_TIMED,
0, 0, &buf ,
(TypCharBuf.TypAhdCnt >= 80 ? 80 TypCharBuf .TypAhdCnt) , 1,
:
&NoTerm,
0, sts
0)) & 01) iosb.sts;
=
if (sts) TypCharBuf .TypAhdCnt
-=
iosb.byteCount ;
A;
i
if (!(sts & 01))
TypCharBuf.TypAhdCnt = 0; /* * Modify characteristics
*/ CharBuf
=
OldCharBuf;
CharBuf.Mode
=
CharBuf.ExtChar
if ((sts 0
_kbhitChan_, IO$_SETMODE, &iosb,
Oo,
(OldCharBuf.Mode =
| TT$M_NOECHO)
OldCharBuf.ExtChar
= sys$qiow
(
& ~TT$M_NOTYPEAHD;
| TT2$M_PASTHRU;
773
+/
8774
ie
/*
*y
PGP Source
Code
and Internals
0, &CharBuf,
125
sts
O))= e011) = iosb.sts;
if (!(sts & 01)) fh
fprintf
(stderr,
"\nttybreak()- Failed to (void) lib$signal (sts); exitPGP (1);
set
terminal
characteristics!");
ay
#ifdef
_USEDCL_
/* * *k-vms_getcmd-Get
VMS
Style
Foreign
Command
*
* Functional
Description:
*
* Get command from VAX/VMS foreign command line interface and parse * according to DCL rules. If the command line is ok, it can then be * parsed according to the rules in the DCL command language table. *
£7,
/*
vms_GetCmd af,
int
vms_GetCmd
(char *cmdtbl)
/* * Arguments: *
*
cmdtbl
Pointer
to
command
table
to
parse.
table
defined
in DROPDCL.CLD
*
* Returns: *
EF
He AIUD
*
* Implicit
Inputs:
*
*
*/
Command
language
*/
/*
File:
‘system.c’
+*/
ti bas Gs char cmdbuf [MAX_CMDSIZ]
unsigned struct
tO;
short
/*
775
;
cmdsiz;
dsc$descriptor
cmdbuf_d
Or Obs Ox;
struct
dsc$descriptor
infile_d =
{05.02.05 0}% char filenm[MAX_FILENM] ; unsigned short filenmsiz; unsigned short verb_size; /*
**
DCL
Parse
**
fake
Expects
A Command
Verb
Prefixing
The
Argumnents
’>
’ characters
it!
*/ verb_size
=
cmdprmt_d.dsc$w_length
cmdbuf_d.dsc$w_length
=
cmdbuf_d.dsc$a_pointer
MAX_CMDSIZ
= strncpy
-
2; /*
-
verb_size
Loose
(cmdbuf,
-
*/
1;
cmdprmt_d.dsc$a_pointer,
verb_size)
at UaGHeloy faslraGy Gp ale
cmdbuf[verb_sizet+] if
((sts
=’
’;
= lib$get_foreign
( /*
Recover
command
line from DCL */
&cmdbuf_d,
O, &cmdsiz, 0)) & 01)
cmdbuf_d.dsc$a_pointer = cmdbuf; cmdbuf_d.dsc$w_length = cmdsiz + verb_size; VAXC$ESTABLISH (lib$sig_to_ret); /* Force unhandled
to return */ sts = cli$dcl_parse
( /*
Parse
Command
Line
exceptions
*/
&cmdbuf_d, cmdtbl,
lib$get_input, lib$get_input, &cmdprmt_d);
} return
(sts);
I /* * **k-vyms_TstOpt-Test
for
command
qualifier
present
ok
* Functional
Description:
*
* This procedure is invoked to test whether an option * really just a jacket routine for the system routine * converting the argument and result into ’C’ speak. * * aS
is present. CLI$PRESENT
It
is
*/
/*
TT6
*/
/*
PGP Source
Code
and Internals
/*
vms_TstOpt |
vms_TstOpt
(char opt)
/*
Arguments:
*
opt
Character
label
of qualifier
to test
for.
Returns:
+1 QO -1
Option Option Option
Implicit He H¥ OK HH HHH Uses
present. absent. negated.
Inputs:
DCL
command
line
context
established
by vms_GetOpt.
*/ int sts; char buf;
struct
dsc$descriptor
i150.
0)
option_d =
Sputs.
buf = _toupper VAXC$ESTABLISH
(opt); (lib$sig_to_ret);
/*
Force
unhandled
exceptions
to return *+/ switch case
(sts = clif$present CLI$_PRESENT:
return
case
(£option_d))
(1);
CLI$_ABSENT:
return (0); case CLI$_NEGATED: return (-1); default:
return
(0);
}
Tee
**-vyms_GetVal-Get
Functional
This KH HHH eH * SS
Value.
Description:
procedure
qualifier
Qualifier
that
is
invoked
exists
to return
(See TstOpt).
the
value
associated
with
a
a¢/
/*
File:
‘system.c’
*/
f*
/*
vms_GetVal 77
vms_GetVal
(char opt,
char *resval,
/* * Arguments:
unsigned short maxsiz)
* *
opt
Character
* *
resval maxsiz
Pointer Maximum
label
of
qualifier
to resulting value size of string.
to test
for.
string.
*
* Returns: *
*
vel DSi. «
*
* Implicit
Inputs:
*
* Uses
DCL
command
line
context
established
by vms_GetOpt.
*/ sf int sts; char buf;
struct {iS -0
dsc$descriptor F505 but};
option_d
struct dsc$descriptor value_d {maxsiz - 1, 0, 0, resval}; unsigned short valsiz;
=
=
VAXC$ESTABLISH (lib$sig_to_ret); to return */ buf = _toupper (opt); if ((sts = cli$get_value (
/*
Force unhandled
exceptions
&option_d, &value_d,
&valsiz)) & 01) resval[valsiz] = return (sts);
’\0’;
} /*
* **-vms_GetArg-Get Functional
This e+ * &
+7
Value.
Description:
procedure
argument.
Argument
is invoked
to return
the value
associated
with an
BTTT
7
/*
778
*/
/*
PGP
Source
Code
and
/*
vms_GetArg */ vms_GetArg
(unsigned
short
arg,
char
*resval,
unsigned
short
maxsiz)
/*
* Arguments: *
*
arg
Argument
* *
resval maxsiz
Pointer Maximum
Number
(1-9)
to resulting value size of string.
string.
*
* Returns: *
>
Pl Bowne
*
* Implicit
Inputs:
*
* Uses
{
DCL
command
line
context
established
by vms_GetOpt.
*/ int
sts;
Gineue (psd (| S Wve struct dsc$descriptor option_d = (2, O5 ©, Vorbeizs struct dsc$descriptor value_d = {maxsiz - 1, 0, 0, resval}; unsigned short valsiz; VAXC$ESTABLISH
to return
(lib$sig_to_ret);
/*
Force
*/
but biJy="arci+
7.07;
if ((sts = cli$present (&option_d)) { if ((sts = cli$get_value (
& 01)
&option_d, &value_d,
&valsiz)) & 01) resvallvalsizi| =
?\02>
else
return (0); return (sts);
}
/* * **-do_help-Invoke *
VMS
Help
Processor
unhandled
exceptions
Internals
*/
/*
File:
‘system.c’
* Functional
*/
/*
779
Description:
*
* This procedure is invoked to display * using the standard VMS help library.
a suitable
help message
to the
caller
*
+7 /*
do_help +*/ do_help
(char *helptext,
char *helplib)
/* * Arguments: *
5
* *
helptext helplib
Text Help
of help request. library.
*
* Returns: *
* As for kbhit_Getchn
and lbr$output_help.
*
* Side
Effects:
*
* A channel
1
+7,
int
may be opened to the
terminal.
A library
is opened.
sts;
int helpflags; struct dsc$descriptor {strlen (helptext), 0, struct dsc$descriptor {strlen (helplib), 0,
helptext_d = 0, helptext};
helplib_d
=
0, helplib};
VAXC$ESTABLISH (lib$sig_to_ret); exceptions to return */
/*
Force
unhandled
if (((sts = kbhit_Getchn ()) & 01) || sts == 0) ! helpflags
= HLP$M_PROMPT
sts = lbr$output_help lib$put_output, &OldCharBuf
| HLP$M_SYSTEM
| HLP$M_GROUP
(
.BufferSize,
&helptext_d, &helplib_d,
&khelpflags,
lib$get_input) ; return (sts); } #Hendif /* _USEDCL_
*/
unsigned long vms_clock_bits[2];
/* VMS Hardware
Clock */
| HLP$M_PROCESS;
*/
/*
780
const
¥*/
/*
long vms_ticks_per_update
= 100000L;
PGP
/* Clock
Source
update
Code
int.
and
*/
* FDL Stuff For Getting & Setting File Characteristics * This code was derived (loosely!) from the module LZVIO.C in the * domain LZW compress routine as found on the DECUS VAX SIG tapes
* given,
Internals
public (no author
so no credits!)
*
/* * **#-fdl_generate-Generate
An FDL
*
* Description: *
* This procedure takes the name of an existing file * an fdl. The FDL is retuned by pointer and length. * released after use with a call to free();
as input and creates The FDL space should
*/ /*
fdl_generate */ int fdl_generate
(char
*in_file,
char
**fdl,
short
*len)
/* * Arguments: *
*
in_file
char*
Filename
fdl
char*
Pointer
len
short
Length
bit
means
of file to examine
(Zero terminated).
*
*
to FDL that
was
*
*
of FDL
*
* Status
Returns:
*
* VMS
{
style.
lower
set
success.
*/ struct
dsc$descriptor
fdl_descr
{0, DSC$K_DTYPE_T, DSC$K_CLASS_D,
0}; struct FAB fab, *fab_addr; struct RAB rab, *rab_addr; struct NAM nam; struct XABFHC xab; Initmsitse
int
badblk;
=
created.
created.
be
*/
/*
File:
‘system.c’
+*/
/*
781
/*
i2 is ta FDL Descriptor
if ('(sts
.
= str$geti_dx
return
(&FDLSIZE,
&fdl_descr))
& 01)
(0);
/*
* Build
*/ fab
RMS
Data
Structures
= cc$rms_fab;
fab_addr
nam rab
=
&fab;
= cc$rms_nam; = cc$rms_rab;
rab_addr
=
&rab;
xab = cc$rms_xabfhc; fab.fab$l_nam = &nam; fab.fab$l_xab = &xab; fab.fab$l_fna = in_file; fab.fab$b_fns = strlen (in_file); rab-rab$lifab = &fab; fab. fab$b_fac FAB$M_GET | FAB$M_BIO; /* * Attempt
open block mode
only */
to Open File
*/ if (!((sts { if
/* This
= sys$open
(&fab))
& 01))
(verbose)
“f fprintf (stderr, "\n(SYSTEM) Failed to $0PEN %s\n", (void) lib$signal (fab.fab$l_sts, fab.fab$1l_stv);
in_file);
} return
(sts);
as if
(fab.fab$l_dev
& DEV$M_REC)
i fprintf sts
=
(stderr,
"\n(SYSTEM)
Attempt
to read
from
output
only
device\n");
0;
} else
rab.rab$l_rop = RAB$M_BIO; if ('((sts = sys$connect (&rab))
& 01))
if if
(verbose)
A fprintf (stderr, "\n(SYSTEM) Failed to $CONNECT %s\n", (void) lib$signal (fab.fab$l_sts, fab.fab$l_stv) ;
} } else
{
if ('((sts
= fdl$generate
(
in_file);
*/
/*
782
*/
/*
PGP
Source
Code
and
Internals
&flags, &fab_addr, &rab_addr,
NULL, NULL, &fdl_descr, &badblk, len)) & 01))
if (verbose) fprintf (stderr, "\n(SYSTEM) inefite); free
Failed to generate
FDL\n",
(fdl);
} else
x
if (!(*fdl = malloc
return
memcpy (void)
(*fdl,
fdl_descr.dsc$a_pointer,
str$freei_dx
sys$close Tetum
*len);
(&fdl_descr);
(&fab) ;
(stsyr:
**-fdl_close-Closes
*
(*len)))
(0);
files
created
by fdl_generate
*
* Description: *
*
This procedure is invoked * allocated by fdlfparse.
to
close
the
file
and release
the
data
structures
*/ /*
fdl_close */ void
fdl_close
(void
*rab)
/*
* Arguments: *
*
rab
VOID
*
* Returns: *
*
*/
None.
uf struct
FAB
*fab;
*
Pointer
to
RAB
(voided
to
avoid
problems
for
caller).
*/
/*
File:
‘system.c’?
fab = ((struct tte
¥*/
/*
RAB *) rab)->rab$l_fab;
(Chab)
f
{ /* Close file if not if (fab->fab$w_ifi) sys$close
783
already
closed */
(fab);
} fdl¢$release
(NULL,
&rab);
/*
**-fdl_create-Create
A File
Using the
recorded
FDL
(hope we get it right!)
Description:
This
procedure
there is no subsystem.
accepts
way
we
can
an FDL and uses easily
patch
it create
into
the
a file.
back
of the
Unfortunately VAX
C I/0
* & *eex*e** SS
/*
fdl_create */ VOID
*
fdl_create
(char
*fdl,
short
len,
char
string
*outfile,
char
*preserved_name)
/* *
Arguments:
*
*
fdl
char*
FDL
len
short
Returned
outfile
char*
Output
descriptor.
*
*
string
length.
*
*
filename.
*
*
preserved_name
char*
Name
from
FDL.
*
* Returns: *
*
{
O in case
of
error,
or
otherwise
*/ VOID *sts; int sts2; struct FAB
*fab;
struct
*rab;
RAB
struct NAM nam; int badblk; char
*resnam;
struct
dsc$descriptor
fdl_descr
=
the
RAB pointer.
*/
/*
784
*/
/*
PGP
Source
Code
len, DSC$K_DTYPE_T, DSC$K_CLASS_S, fdl
Fi sts
= NULL;
/*
* Initialize
RMS
NAM
Block
*/ nam = cc$rms_nam; nam.nam$b_rss = NAM$C_MAXRSSLCL; nam.nam$b_ess = NAM$C_MAXRSSLCL; if ('(resnam = nam.nam$l_esa = malloc af
fprintf return
/* * Parse
(stderr,
"\n(FDL_CREATE)
(NAM$C_MAXRSSLCL
+ 1)))
Out of memory! \n") ;
(NULL);
FDL
7
if ('((sts2
= fdl$parse
(&fdl_descr,
&fab, &rab,
&flags)) {
& 01))
fprintf
(stderr,
(void)
lib$signal
"\nCreating
(fdl$parse)\n");
(sts2);
else
af /* * Extract
& Return
Name
of FDL
Supplied
Filename
aif memcpy (preserved_name, fab->fab$l_fna, preserved_name[fab->fab$b_fns] = ’\0’; /*
* Set
Name
Of Temporary
File
*/ fab->fab$l_fna
= outfile;
fab->fab$b_fns
= strlen
/* * Connect
NAM
(outfile);
Block
*/ fab->fab$l_nam fab->fab$1_fop
= &nam; |= FAB$M_NAM
| FAB$M_CIF;
fab->fab$b_fac
|= FAB$M_BIO
| FAB$M_PUT;
/*
* Create
File
*/ if ('(sys$create
(fab)
& 01))
fab->fab$b_fns) ;
and
Internals
*/
/*
File:
‘system.c’
+*/
/*
785
{ fprintf (stderr, "\nCreating (RMS)\n"); (void) lib$signal (fab->fab$l_sts, fab->fab$1_stv); fdl_close
+
(rab);
else
{
if (verbose)
i;
resnam[nam.nam$b_esl + 1] = ’\0’; fprintf (stderr, "\nCreated %s successfully\n",
resnam) ;
rab->rab$l_rop = RAB$M_BIO; if [ (!(sys$connect (rab) & 01))
fprintf
(stderr,
(void)
lib$signal
fdl_close
"\nConnecting
(RMS)\n");
(rab->rab$l_sts,
rab->rab$l_stv) ;
(rab);
else sts
=
rab;
M, so
fab->fab$l_nam = 0; /* I allocated I must deallocate it! */
NAM block,
free (resnam) ; return (sts);
} /* * **-fdl_copyfile2bin-Copies
the
input
file
to a
’binary’
output
file
*
* Description: *
* * * *
This procedure is invoked to copy from an opened file f to a file opened directly through RMS. This allows us to make a block copy into one of the many esoteric RMS file types thus preserving characteristics without blowing up the C RTL. This code is based directly on copyfile from FILEIO.C.
oe
* Calling
Sequence:
*/ /*
fdl_copyfile2bin +/ int fdl_copyfile2bin *
* Arguments: *
(FILE
* f, VOID
* rab,
word32
longcount)
a7
/*
T86
*
*/
/*
ai
FILE*
Pointer
to
input
rab
RAB*
Pointer
to
output
longcount
word32
Size
PGP Source
Code and Internals
file
*
*
file
RAB
*
*
of file
*
* Returns: *
£
*
0
If we
* *
-1 +1
We had an error We had an error
were
successful.
on the input file (VAXCRTL). on the output file (direct RMS).
7, int
status = 0; count; ((struct RAB *) rab)->rab$l_rbf
&textbuf ;
((struct
0;
word32
RAB
*) rab)->rab$1_bkt
do
{ /*
Read
and write
count
if (longcount = longcount;
count
else = DISKBUFSIZE;
longcount
< (word32)
count = fread (textbuf, cise ((@oinsigs = (0)
bytes
*/
DISKBUFSIZE)
1, count,
f);
{
/* * *
No byte order conversion required, source VMS so have the same byte ordering.
*/ ((struct RAB *) rab)->rab$w_rsz if ('!(sys$write (
and target
= (unsigned short)
rab,
NULL, NULL)
& 01))
{ lib$signal (((struct RAB *) rab)->rab$l_sts, ((struct RAB *) rab)->rab$l_stv); status break;
} longcount
=
-=
1;
count;
} while (count == DISKBUFSIZE) ; burn (textbuf); return (status);
} /*
* **-vms_fileparse-Parse
A VMS
File
Specification
system
count;
are
both
aif
File:
Ps*
‘system.c’
Functional
*/
/*
Description:
This procedure is invoked to parse and related specifications to fill little like DCL’s F$PARSE function (that is we don’t check the device spec is really for when we want to directory) to supply the name of an
a VMS file specification using default in any missing components. This works a with the syntax check only specified or the directory). The related file use the name of an input file (w/o the output file.
Note that we correctly handle the situation where the output the input filespec by testing for the case and then handling OF He HE EH eH “eee the primary input specification to a temporary buffer before
buffer overlays it by copying parsing.
* ~~
/*
vms_fileparse */ int vms_fileparse /* * Arguments:
(char
*outbuf,
char
*filespec,
char
*defspec,
*
*
outbuf
Returned
* * *
filespec defspec relspec
Primary Default Related
file
file file file
specification.
specification specification specification
*
* Returns: *
*
As
for
SYS$PARSE.
*
* Implicit
Inputs:
*
*
None.
*
* Implicit
Outputs:
*
*
None.
*
* Side
Effects:
*
*
{
5 oAlieisye
*/ struct struct
FAB fab = cc$rms_fab; NAM nam = cc$rms_nam;
struct
NAM rlnam
intests)
int char
=
787
= cc$rms_nam;
1;
len; tmpbuf
[NAM$C_MAXRSSLCL]
;
(optional). (optional). (optional).
char
*relspec)
+/
788
/*
char
*/
/*
PGP
Source
Code
and
Internals
expfnam2[NAM$C_MAXRSSLCL];
slat (outbuf
!= NULL)
CKetwlowae [Ol] =
Pe)? 5
fab.fab$l_fop nam.nam$b_nop
!= FAB$M_NAM; /* Enable RMS NAM block processing |= NAM$M_PWD | NAM$M_SYNCHK;
/*
**
Handle
/
if (relspec ste ((len
Related
Spec
(If reqd).
!= NULL)
= strlen
(relspec))
> 0)
fab.fab$l_nam = fab.fab$b_fns = fab.fab$l_fna = rlnam.nam$b_ess
&rlnam; len; relspec; = NAM$C_MAXRSSLCL;
rinam.nam$l_esa
=
expfnam2;
rlnam.nam$b_nop |= NAM$M_PWD if ((sts = sys$parse (
| NAM$M_SYNCHK;
&fab,
0, 0)) & 01) rlnam.nam$l_rsa
= rlnam.nam$l_esa;
rinam.nam$b_rsl
=
rlnam.nam$b_es1;
nam.nam$1_rlf
= &rlnam;
fab.fab$l_fop
|= FAB$M_OFP;
i TE
ACsts)
fab.fab$l_nam nam.nam$l_esa nam.nam$b_ess
=
& nam ;
= outbuf; = N AM$C_MAXRSSLCL;
/*
**
Process
7, if (defspec if
((len
Specification:
!= NULL) = strlen
fab.fab$l_dna fab.fab$b_dns
**
Default
Process
(defspec))
> 0)
defspec; len;
Main
File
Specification:
*/
*/
/*
File:
‘system.c’
fab.fab$l_fna fab.fab$b_fns
*/
/*
789
= NULL; = 0;
if (filespec != NULL) { if ((len = strlen fab.fab$b_fns
(filespec))
> 0)
= len;
if (filespec == outbuf) fab.fab$l_fna = memcpy
(tmpbuf,
filespec,
len);
else
fab.fab$l_fna = filespec; } if ((sts
= sys$parse
(
&fab,
0, 0)) && 01) :
outbuf [nam.nam$b_esl] } return
=
’\0’;
(sts);
}
#endif
/* VMS */
aa
ee
a
ee
a
ee
oe
ee
ea
a
a
ae
ee
/*
aa
ae
SS
a
* AMIGA
*/
#ifdef
AMIGA
#include #include #include #include #ifdef
stuff
*/
LATTICE
#include #include #endif extern extern
/* Amiga-specific
/* LATTICE */ FILE *pgpout; int
aecho;
/* amiga version of getch() Cor
Bosman
+/
sendpacket struct struct
, jul-22-92
(struct
MsgPort
StandardPacket msgPort *rp;
*rec,
*pkt;
LONG
action,
LONG
arg1)
*/
/*
790
LONG
*/
resi
/*
=
PGP Source
*) CreatePort
(NULL,
OL))
if (pkt = (struct StandardPacket *) \ AllocMem (sizeof (struct StandardPacket), MEMF_PUBLIC pkt->sp_Msg.mn_Node.1n_Name pkt->sp_Pkt.dp_Link pkt->sp_Pkt.dp_Port pkt->sp_Pkt.dp_Type pkt->sp_Pkt.dp_Argi
= = = =
| MEMF_CLEAR))
= (BYTE *) & pkt->sp_Pkt;
&pkt->sp_Msg; rp; action; arg1;
PutMsg (rec, &pkt->sp_Msg) ; WaitPort (rp); GetMsg (rp); resi = pkt->sp_Pkt.dp_Res1; FreeMem ((UBYTE *) pkt, sizeof
DeletePort
(struct
StandardPacket)) ;
(rp);
ip (resi);
} / * ttycbreak for amiga. * Cor
Bosman
, jul-30-92
e/,
,*
ttycbreak *
/
Vv oid
ttycbreak { YI
sha,
() Ghrg
char buf[1i28]; struct MsgPort
in = Input out
();
ch = ((struct
I:
*ch;
();
= Output
sendpacket
FileHandle
(ch,
a
Bosman
*) BADDR
ACTION_SCREEN_MODE,
/ * ttynorm for amiga * Cor
and Internals
OL;
if (rp = (struct MsgPort
return
Code
, jul-30-92
(in))->fh_Type; -1L);
*/
/*
File:
‘system.c’
¥*/
/*
/*
ttynorm */ void
ee
()
BPTR
in,
out;
char buf[128]; struct MsgPort in = Input
*ch;
();
out = Output (); ch = ((struct FileHandle ; sendpacket
(ch,
*) BADDR
ACTION_SCREEN_MODE,
/*
getch */ char
getch (void) a éhar -buf[128]; BPIRe
In
Out;
in = Input
();
out = Output (); Reade(ian.) but. 1); if (aecho) Write (out, buf, return (buf[0]);
1);
}
/* kbhit() * Cor
function for amiga.
Bosman
, jul-30-92
*/ /*
kbhit */ int
kbhit () { if (WaitForChar return 1; return 0;
i;
(Input
(), 1))
(in))->fh_Type; OL);
(oil
*/
fe
INTO2
#ifdef
/*
=e/
PGP Source
Code
LATTICE
/*
*
Lattice-C
~“C-Handler
*/ /*
Che int CXBRK
()
af BPTR
in,
struct
out;
MsgPort
ing=) Input out
*ch;
();
= Output
();
/* it might happen we catch * so always set the screen
df
ch =
((struct
sendpacket
fprintf exitPGP
FileHandle
(ch,
a “C while in cbreak to the normal mode.
*) BADDR
mode.
(in) )->fh_Type;
ACTION_SCREEN_MODE,
OL);
(pgpout, "\n*+#* Program Aborted. \n") ; (6); /* INTERRUPT */
#Hendif
* clock.c
--
time
in microseconds
since
first
call
*
* RP:
this
function
is missing
from
SAS/C
*/ #include
/*
clock */ long
clock:
()
{
static unsigned long oldms unsigned long c1[2], ms; timer
(cl);
ms
= cl[0]
if
(oldms
* 1000000 ==
-1)
{ oldms = ms; return 0;
+ cl[i]
% 1000000;
library.
of
clock()
and
Internals
*/
/*
File:
‘system.c’
*/
/x
EF else
return
#endif
((long)
/* AMIGA
* other
stuff
(ms - oldms));
*/
for
non-MSDOS
systems
*/ #ifdef ATARI #include #endif #if
!'defined(MSDOS)
&&
#include
#include
''charset.h"
char
!defined (ATARI)
*
strlwr
(char *s)
4 /* #*
Turns
string
s into
lower
case.
*/. sireke (5 char *p =
s;
while (c = *p) *pt+ = to_lower return (s); } #tendif
/*
!MSDOS
&&
(c); ! ATARI
*/
/*
ey.
MV
Sstuestr
#Hifdef #undef
strstr strstr
/* Not
implemented
char
on
some
systems
*
mystrstr
(char *si,
shake Ge char *strchr
if (!s2 return
();
|| !*s2) s1;
char *s2)
-
return
first
instance
of
s2
in
si
*/
(ge
*/
/*
794
*/
/*
PGP
Source
Code
for: (=) { gf return
eCi¢cte=erstrchr
(si,
*s2)))
si;
for (i = 1; s2fi)
&& (sili)
== s20iJ);
++i)
gf 9('s2[i)) return
s1;
+t+3S1;
} #endif
/* strstr
#ifdef #undef
fopen fopen
#ifdef
ATARI
#define
*/
F_BUF_SIZE
8192 /* seems
to be a good value
...
*/
/*
myfopen */ FILE
*
myfopen (const char *filename, const char *mode) /* Open streams with larger buffer to increase disk /* Adjust F_BUF_SIZE to change buffer size.
I/0 speed.
*/ */
{ ISA,
ees
if ((f = fopen if
(setvbuf
fclose
(f);
f = fopen : return
#else
(filename, (f, NULL,
/* then
(filename, (f);
close
/* ATARI
it again
mode);
/* return
mode)) _IOFBF,
!= NULL) F_BUF_SIZE))
either
handle
*/
myfopen FILE
"b" from
2nd arg */
*
myfopen char
(char *filename, buf[1i0];
*/
*/
/* and try again in normal
/*
*/ /* Remove
/* no memory?
char *type)
or NULL
*/
mode
*/
and
Internals
+/
/*
File:
‘system.c’
¥*/
buf [0] = *typet++; if (*type == ’b’) ++type;
strcpy
(buf + 1, type);
return
fopen
#endif #Hendif
(filename,
/* not ATARI /* fopen */
buf);
*/
#ifndef MSDOS #ifdef OS2 static
eant
chr)
=
—1;
/*
kbhit */ int
kbhit (void) { af) (chr ==
—1)
chr e=)-read_kbd return
(chr
(0, 0, 0);
!= -1);
Ai /*
getch */ int
getch
(void)
t int. c;
if (chr >= 0) {
@ 2 ibe
iibgy Cale
} else
c = _read_kbd return
c;
t; #endif #Hendif
/* OS2 */ /* MSDOS */
(0,
1, 0);
/*
795
*/
/*
796
*/
/*
J/imrnsler
“usnalseh?
/* (New File)
/* usuals.h */
PGP
Source
-*&/
*/
- The usual typedefs, /* Assures
etc.
#ifndef
USUALS
#define
USUALS
typedef typedef typedef typedef typedef
unsigned char boolean; /* values are TRUE or FALSE unsigned char byte; /* values are 0-255 */ byte *byteptr; /* pointer to byte */ char *string; /* pointer to ASCII character string unsigned short wordi6; /* values are 0-65535 */
#ifdef
no redefinitions
of usual
types...
__alpha
typedef
unsigned
int word32;
#else typedef
/* values
unsigned
long word32;
are 0-4294967295
/* values
are
*/
0-4294967295
#Hendif
#ifndef #define #define
#Hendif #ifndef #define
TRUE FALSE 0 TRUE (!FALSE)
/* if TRUE not already min /* if min macro min(a,b) (((a)(b))
/* if min macro
/* void for use #ifndef #define
not
in pointers
defined */
not already defined ? (a) : (b) )
*/
? (a) : (b) ) already
defined
*/
*/
NO_VOID_STAR VOID void
#else
#define #tendif
VOID
char
/* Zero-fill the byte buffer. */ #define £i1110(buffer,count) memset(
buffer,
0, count
)
/* This file
macro is for burning sensitive data. Many of the I/O routines use it for zapping buffers */
#define
burn(x)
#endif
Code
fill0((VOID
/* if USUALS
not
*)&(x) ,sizeof(x))
already
defined
*/
*/
*/ */ */
and
Internals
+7
/*
File:
‘zbits.c’
/ +i Faille:
*/
/*
‘zbate:.c?
T97
ak/
/* (New File) */ /*
Copyright
(C) 1990,1991
Mark Adler,
Richard B. Wales,
and Jean-loup
Gailly.
Permission is granted to any individual or institution to use, copy, or redistribute this software so long as all of the original files are included unmodified, that it is not sold for profit, and that this copyright notice is retained. SS ~~*
bits.c This
by Jean-loup
is a new
Gailly.
version
of
im_bits.c
originally
written
by Richard
B.
Wales
PURPOSE
Output
variable-length
bit
strings.
DISCUSSION
The PKZIP "deflate" file format interprets compressed as a sequence of bits. Multi-bit strings in the file byte boundaries without restriction.
The
first
bit
of
each
byte
is the
The routines in this file allow be output right-to-left (useful left-to-right
output
the bits must
have been reversed
(useful
low-order
file data may cross
bit.
a variable-length bit value for literal values). For
for
code
strings
from
the
tree
to routines),
first with bi_reverse().
INTERFACE
void bi_init
(FILE *zipfile)
Initialize
the bit
void send_bits Write
out
string routines.
(int value, a bit
string,
int length) taking
the
source
bits
right
to
left.
int bi_reverse Reverse
right
(int value,
the
and
bits
of
emitting
string,
them right
void bi_windup (void) Write out any remaining HEHE KKH KEH KEK KKH HHH HH HHH HHH HK KKH HH KH
int length)
a bit
bits
taking
the
source
to left. in an
incomplete
byte.
bits
left
to
*/
/*
798
*
*/
/*
void
* t
copy_block(char
far *buf,
PGP
unsigned
Source
len,
Copy a stored block to the zip file, its one’s complement if requested.
Code
and
Internals
int header)
storing
first
the
length
and
*
*7, #include /*
=
"zip.h"
Sf
* Local
7
local
555555555555
data
FILE
used
by the
*zfile;
555555
"bit
/* output
5555
string"
zip file
local unsigned short bi_buf; /* Output buffer. bits are inserted * bits).
5555555555
55555
555
5555555555
55
SS
ES SSS
SS
routines.
*/ ; at the bottom
starting
(least
significant
cai
#define Buf_size (8 * 2*sizeof(char) ) /* Number of bits used within bi_buf. (bi_buf might be implemented on * more
than
16 bits
on
some
systems.)
*/ local int bi_valid; /* number of valid bits in bi_buf /* All bits above the last valid bit are always zero.
*/
yf #ifdef DEBUG ulg bits_sent; #endif
/* Output #define
/* bit
length
a 16 bit value
PUTSHORT(w)
(eCvoid)ezputce (void) zputc
/* Output
to the bit
SSS
SS
SS
SS
SS
+/
stream,
value
to the bit
SS
ES SS
the
SS
bit
SS
SS
SS
stream,
& Oxff),
SS
string
SS
SS
SS
SS
SS
SS
routines.
Diane */
(zipfile)
FILE *zipfile;
ab zfile
= zipfile;
(esl lied > 8), zfile);
an 8 bit
* Initialize
compressed
\
#define PUTBYTE(w) \ { (void) zputc ((char)((w) ty /*
of the
right
to left
*/
\
SS
SS
SS
SSS
SSS
SS
ee
eee
eee
eee
eee
eer
x/
/*
File:
‘zbits.c?
*/
/*
799
bi_valid = 0; #ifdef DEBUG bits_sent = OL; #endif
} /*
SSS
SS
SSS
SSS
SS
SS
SSS
SS
SS
SSS
SSS
SS
SSS
SS
SS
SSS
SS
SS
* Send a value on a given number of bits. * IN assertion: length 0 && length b) e -= 16; NEEDBITS (e)
while
((e =
(t = t->v.t
DUMPBITS
dat (@ 22
1G)
slide[wt+] if
\Gwe ==)
+
(b & mask_bits[e]))->e)
(t->b)
72 Wang
sige
a Wegecreul
= t->v.n; WSIZE)
{ flush w=
(w);
0;
iF } else
/* it’s £
an EOB or a length */
/* exit rae
(ey Se
if
end
Sl[5))
of block
*/
23//
> 16);
and
block.
bits
*/
Internals
tables
*/
*/
/*
File:
‘zinflate.c’
+/
/*
break;
/* get length of block to copy */ NEEDBITS
(e)
n = t->v.n DUMPBITS
+ (b & mask_bits[e]);
(e);
/* decode distance NEEDBITS (bd)
of block
to
copy
if ((e = (t = td + (b & md))->e)
*/
> 16)
4 af aGem==199)) return 1; DUMPBITS (t->b) e -= 16; NEEDBITS (e)
5 while
((e =
(t = t->v.t
+
(b & mask_bits[e]))->e)
> 16);
DUMPBITS (t->b) NEEDBITS (e)
d =w
- t->v.n
DUMPBITS
-
(b & mask_bits[e]);
(e)
/* do the copy */ do
£
ne—= (e =.(e #ifndef NOMEMCPY
if
= WSIZE
—
((d &= WSIZE
(w - d >= e) /* (this test
-
assumes
1) > wi2.d-:
unsigned
% memcpy (slide w t= e; d +=
}
+ w,
slide
+ d,
e;
else
/* do it slow to avoid memcpy()
#eendif /* !NOMEMCPY */ do
slide[w++] while
flush
Cwe==sWSLZE)
(w);
0;
WhaslewGn)s
}
IP
= slide[d++] ;
(--e); if
w=
e);
overlap
*/
w)).>.n.?
comparison)
n-:.e);
*/
835
*/
836
/*
*/
/*
PGP
Source
/* restore the globals from the locals */ wp = w; /* restore global window pointer */ bb = b; /* restore global bit buffer */ bk
= k;
/* done return
*/ 0;
/*
inflate_stored */ int
inflate_stored /*
af
()
"decompress"
an inflated
unsigned n; /* number unsigned
w;
type 0 (stored)
of bytes
/* current
window
unsigned
k;
copies
/* number
/* make
local
b = bb;
/* initialize
bit
/* initialize
window
*/
*/ of bits
of globals
in bit
*/
buffer
*/
k = bk;
w=
wp;
/* go to byte boundary
position
*/
*/
Ne= Ka 8 DUMPBITS (n);
/* get the length and its complement
*/
NEEDBITS (16) ny ES |e) 5 (Ob Gisentail DUMPBITS (16) NEEDBITS (16) ite(me=" Cob) &0xffit) ) return
DUMPBITS /* read
while
“t
1; /* error
in compressed
data
*/
(16) and
output
(n--)
the
*/
in block */ position
register ULONG b; /* bit buffer register
block.
compressed
data
*/
buffer
*/
Code
and
Internals
*/
/*
File:
‘zinflate.c’
NEEDBITS
slide[wt+] if
flush w=
*/
Vk
(8)
= b; (w ==
WSIZE)
(w);
0;
DUMPBITS
(8)
/* restore the globals from the locals */ wp = w; /* restore global window pointer */ bb = b; /* restore global bit buffer */ bk = k; return 0;
‘
/*
inflate_fixed
=A/
int
inflate_fixed () /* decompress an inflated type 1 (fixed Huffman codes) block. We should either replace this with a custom decoder, or at least precompute the
Huffman tables.
*/
{ int
i; /* temporary
variable
*/
struct
huft
*tl;
/* literal/length
struct
huft
*td;
/* distance
code
int bl;
/* lookup bits
for tl */
int
/* lookup
for
bd;
unsigned 1[288];
"="0-
*/
*/
td */
/* length list for huft_build */
/* set up literal for(i
bits
code table table
table
i < 144;
*/
i++)
Liale= "8; for
(; i < 256;
itt)
1fi] = 9; for
280;
i++)
1 Pae= shy for (; i < 288;
(:—-i-
-="huftsebuidd?(1,
5;
430,10
bepdists/
cpdext,
> 1)
{ huft
free
return
(tl);
i;
/* decompress
until
an end-of-block
ifmCintlatescodess(tileatd.abl. return
/* free
*/
1;
the decoding tables,
huft_free huft_free return
code
ba)
return
*/
(t1); (td);
0;
/*
inflate_dynamic +/ int
inflate_dynamic () /* decompress an inflated
30) 1; /* bad lengths */ in bit-length-code
for’ (i = 0; {
i < nb;
NEEDBITS
lengths
*/
i++)
(3)
UAL | hevowatelere Mt| i) = je Ca 768 DUMPBITS
(3)
} siope
(CR Gi b;
| =
WG
DUMPBITS
11[it+]
n)
1;
(j--)
ii fits
=0;
L=..0;
} else
/* j ==
18:
11 to 138 zero
NEEDBITS
length codes
*/
(7)
fea 1iete(b DUMPBITS
820x772);
(7)
if? (4 return
ja >on) 1;
while (j--) Liisi) F=e"0; 1 =
0;
} }
/* free decoding huft_free (tl);
/* restore bb bk
table
for trees
*/
the global bit buffer
*/
= b; = k;
/* build the decoding tables bl
=
for literal/length
if?CCi
"= "huftsbuild
(Il
}inlye267,
ecpliens,
a if
(i ==
1)
huft_free (tl); return i; /* incomplete
A:
and distance
codes
lbits;
code
set
*/
Fcplextyestl,’
&bl))
=
0)
*/
*/
(*
eFilecvaSzinflate)clon) */
/*
bd = dbits; aS
= huft_build
(11 + nl,
nd,
0, cpdist,
cpdext,
&td,
if (i == 1) huft_free (td); huft_free (tl);
+
return
i; /* incomplete
/* decompress if
until
(inflate_codes return
code
an end-of-block (tl,
td,
bl,
*/
code
*/
bd))
1;
/* free the decoding tables, huft_free huft_free return
set
return
*/
(tl); (td);
0;
/*
Bs ene
|eherels
int
inflate_block
(e)
int *e; /* last block flag /* decompress an inflated block
{
unsigned
t; /* block
register
ULONG
b;
type */
/* bit
buffer
register unsigned
k; /* number
/ * make b = bb; k
local
buffer
/* read
in last
NEEDBITS * e=b DUMPBITS
/* read
block
bit
(1) & 1; (1)
in block
NEEDBITS
(2)
ae SS [s) ts GIG
DUMPBITS
bit
(2)
*/ */
type */
+*/
*/
*/
of bits
in bit buffer
*/
&bd))
!= 0)
841
7,
jx
MSA2
%/
:
/*
PGP
/* restore the global bit buffer */ ibbw=s bi: bk
=
k;
/* inflate that block type */ if (t == 2) return inflate_dynamic (); if (t == 0) return
if (t == return
inflate_stored
();
1) inflate_fixed
();
/* bad block type */ return
2;
/*
inflate_entry */ int
inflate_entry /* decompress u
() an inflated
entry */
int e; /* last block flag */
int r; /* result code */ unsigned h; /* maximum struct /* initialize ’ wp bk bb
window,
bit
huft’s
buffer
malloc’ed
*/
. ’
. ete(e)s) i) (2),
/* decompress h = do
until
the
last
block
*/
0;
{ hufts
if return
=
0;
((r =
qf Ghuttss h = hufts;
i; while
inflate_block
r;
('e);
>. h)
(&e))
!= 0)
*/
Source
Code
and Internals
*/
/*
~File:+,‘zinflate.c?.«
/* flush out flush (wp); /* return #ifdef
slide
success
*/
/*
*/
*/
DEBUG
fpmintt «(etderr, ¢'.s"'7 #endif /* DEBUG */ return
h);
0;
} /*
inflate +/ int
inflate
()
/* ignore
the
return
code
for
now
...
*/
{ int
status;
#ifdef
DYN_ALLOC
window
= (char *) calloc
/* Note *
that
array
+7.
is
if (window err
(4,
inflate shared
((unsigned)
only needs
with
deflate,
== NULL) DIC)
#endif
status
= inflate_entry
#ifdef
DYN_ALLOC
free
(window);
window #endif return
}
=
NULL;
status;
();
WSIZE,
WSIZE which
bytes, needs
2 * sizeof but
(char));
the
window
2+*WISZE
bytes.
843
*/
/*
844
*/
/ ee
;
eee
/* (New File)
/*
PGP
Source
Code
and
Internals
hes,
*/
/*
Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as all of the original files are included unmodified, that it is not sold for profit, and that this copyright notice is retained.
+/
/* *
Zip.h
by Mark
Adler.
*/
/* Set up portability #include #define #define
*/
"ztailor.h" MIN_MATCH MAX_MATCH
/* The minimum
3 258
and maximum match
lengths
*/
#ifndef WSIZE #define WSIZE 8192 /* for PGP only use 8192 */ #endif /* Maximum window size = 32K. If you are really short of memory, compile * with a smaller WSIZE but this reduces the compression ratio for files * of size > WSIZE.
+y,
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the * See deflate.c for comments about the MIN_MATCHt+1.
input
#define MAX_DIST (WSIZE-MIN_LOOKAHEAD ) /* In order to simplify the code, particularly on 16 bit * distances are limited to MAX_DIST instead of WSIZE.
machines,
file.
*/
#7; #include
/* Define #ifndef
#define
#Hendif
fseek()
commands
SEEK_SET
SEEK_SET
0
/* !SEEK_SET
*/
#ifndef SEEK_CUR #define SEEK_CUR 1 #Hendif /* !SEEK_CUR
*/
#ifndef #define
SEEK_END SEEK_END
2
*/
match
=,
/*
sePale: tak zips
#endif
/*
h?hod*/
!SEEK_END
/* For setting
/*
+/
stdout
to binary’*/
#ifdef MSDOS #include #include
#endif
/* MSDOS
*/
/* Types centralized #define local static typedef typedef
unsigned unsigned
here for easy modification */ /* More meaningful outside functions
typedef unsigned long ulg; /* Error #include
return codes "ziperr.h"
/* Internal #define #define #define
and
attributes
/* unsigned 32-bit value */ PERR
macro
*/
*/
UNKNOWN -1 BINARY O ASCII 1
/* Public
globals
#define
BEST
#define
STORE
#define
*/
char uch; /* unsigned 8-bit value */ short ush; /* unsigned 16-bit value */
-1
*/
/* Use
best
0 /* Store
DEFLATE
8 /* Deflation
extern
int method;
extern
int
level;
/*
DEBUG
extern
char
verbose;
#ifdef MSDOS #undef stderr #define stderr
(deflation
or
store)
*/
compression
method
*/
*/ method
/* Restriction Compression
/* Diagnostic functions #ifdef
method
method
on
+*/
level
*/
*/
/* PGP
-l
flag
*/
stdout
#endif
#define diag(where) fprintf(stderr, "zip diagnostic: %s\n", #define Assert(cond,msg) {if(!(cond)) error(msg) ;} #define Trace(x) fprintf x #define Tracev(x) {if (verbose) fprintf x ;} #define Tracevv(x) {if (verbose>1) fprintf x ;} #define Tracec(c,x) {if (verbose && (c)) fprintf x ;} #define #else
Tracecv(c,x)
{if
#define diag(where) #define Assert (cond,msg) #define Trace(x) #define Tracev(x) #define Tracevv(x) #define
Tracec(c,x)
(verbose>1i
&&
(c))
fprintf
x
;}
where)
845
*/
/*
846
#define #endif
*/
function
J/* Anazip.c,
prototypes
read_buf
#define #define
PGP
Source
Code
*/
Zipcloak.c,aorgzipsplit.c
err OF ((int c, error OF ((char
OF
¥/
char *h)); *h));
/* in zipup.c */ int zipup OF ((FILE * inFile, int
/*
Tracecv(c,x)
/* Public void void
,
((char
zfwrite fwrite zputc putc
far
FILE
* buf,
/* 7??? far
/* in deflate.c */ void lm_init OF ((int pack_level, ulg deflate OF ((void));
* outFile)); unsigned
size));
*/
ush
* flags));
/* in trees.c */ void ct_init OF ((ush * attr, int *Method)); inGuctetalivysor ((inttdist, int ic)); ulg flush_block OF ((char *buf, ulg stored_len,
int
eof));
/* in bits.c */ void bi_init OF ((FILE * zipfile)); void send_bits OF ((int value, int length));
unsigned bi_reverse OF ((unsigned value, int length)); void bi_windup OF ((void)); void copy_block OF ((char far * buf, unsigned len, int header)); /* end of zip.h */
and
Internals
*/
Ge
= BilepaYzipac’s
/* (New File) get
*/
code
exact
for
the
errors,
"usuals.h" "fileio.h" "language.h" "pgp.h"' "exitpgp.h"
#include
"ziperr.h"
Issue
error
code
ZIPDEBUG
/* for ZE_MEM
exit:
a message
zip/unzip
define
#include #include #include #include #include #include #include
/* Clean
/*
“zaipec—*/
Pe bile:
/* Support
hy %/
the
just handles
(and errors[]
c is a ZE_-class for
-
error,
error
messages.
error,
clean
if ZIPDEBUG
*msg
up files
defined)
is an error and memory,
exit
err
*/ void
(int c, char *msg)
#ifdef if
ZIPDEBUG (PERR
perror forintr
#endif
(c))
("zip error"); (stderr,
/* ZIPDEBUG
‘zip
erro:
(ies) \n";.errors[e
=
1], msg);
*/
/* Complain and return if (c == ZE_MEM)
{
4s
and
out
of memory
error
code
*/
fprintf exitPGP
(stderr, (7);
LANG
("\nOut
fprintf /* Yuck exitPGP
(stderr, */ (23);
LANG
("\nCompression/decompression
of memory\n"));
}$ else
é }
/* Internal
error,
should
never
happen
*/
*/
message. and
/*
err
To
*/
error\n"));
*/
847
ay
/*
848
*/
/* error
/ void
error err
}
(char *msg) (-1,
msg);
/*
PGP
Source
Code
and
Internals
*/
/*
File:
‘ziperr.h’
/* File:
¥*/
/*
‘ziperr.h’
/* (New File)
849
*/
*/
/*
Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as all of the original files are included unmodified, that it is not sold for profit, and that this copyright notice is retained.
*
*/
ziperr.h
/* Error of
return
PKZIP.
by PKZIP,
#define #define #define
by Mark
Adler.
values.
The
The values so the codes
ZE_MISS ZE_OK ZE_EOF
values
4..10 5..10
are are
0..4
and
12..18
follow
-1 /* used by procname(), zipbare() 0 /* success */ 2 /* unexpected end of zip file */
#define
ZE_FORM
3 /* zip file
#define #define #define #define
ZE_MEM ZE_LOGIC ZE_BIG ZE_NOTE
4 5 6 7
#define
ZE_ABORT
9 /* user
#define
ZE_TEMP
10 /* error using a temp file */
#define #define #define #define #define #define #define
ZE_READ ZE_NONE ZE_NAME
11 12 13 14 15 16 18
/* Macro #define
ZE_WRITE ZE_CREAT
ZE_PARMS ZE_OPEN to
determine
PERR(e)
#ifdef GLOBALS /* Error messages char *errors[] =
/* /* /* /* /* /* /*
whether
(e==ZE_READ|
for
the
error
memory" */
*/
*/
or termination
*/
read or seek error */ nothing to do */ missing or empty zip file */ error writing to a file */ couldn’t open to write */ bad command line */ could not open a specified file to call perror() or not */
| e==ZE_WRITE]|
err()
function
1
2 */ "Unexpected end of zip file", 3 */ "Zip file structure invalid", 4 */ "Out of memory",
Ue
§& */ "Internal logic error",
/* /*
6 */ "Entry too big to split", 7 */ “Invalid comment format",
/*
8
sae
structure
interrupt
/* /* /*
*/
conventions
out of memory */ internal logic error */ entry too large to split */ invalid comment format */
/*
/*
* /
/* /* /* /*
the
all assigned to “insufficient used here for other purposes.
| e==ZE_CREAT|
in the
to read
| e==ZE_TEMP
zip programs
*/
*/
| | e==ZE_OPEN)
*/
/*
/*
850
*/
.
/*
PGP
9 */ "Interrupted",
/* 10 /* 11
*/ “Temporary file failure", */ "Input file read failure",
/* /* /* /* /* 7 /*
*/ */ */ */ */ / */
12 13 14 15 16 erie 18
"Nothing to do!", "Missing or empty zip file", "Output file write failure", "Could not create output file", "Invalid command arguments", >
"File
not
found
extern
'GLOBALS */ char *errors[];
#endif
/* ?GLOBALS
#else
or no
read
permission",
/*
*/
/* Error messages
for err()
*/
Source
Code
and
Internals
= 2 (for end-of-line
t unsigned
len
len;
= zread
if (len ==
(ifile,
buf,
(unsigned)
return len; return len;
EOF
size);
|| len == 0)
file,
and update
translation)
*/
the
crc
and
+¥*/
/*
File:
‘zrevisio.h’
/* File:
*/
/*
‘zrevisio.h’
855
*/
/* (New File) */ /*
Copyright
(C)
1990-1992
Mark Adler,
Richard
B. Wales,
and Jean-loup
Gailly.
Permission is granted to any individual or institution to use, copy, or redistribute this software so long as all of the original files are included unmodified, that it is not sold for profit, and that this copyright notice is retained.
*/
/* *
xrevision.h
by Mark
Adler.-
7 #define #define
REVISION 15 REVDATE '17th
/* Copyright * those
notice
(zip,
February
for binary
zipcloak,
1992" executables--this
zipsplit,
and
zipnote),
notice not
only applies
to this
to
file
* (revision.h).
*/ #ifndef
NOCPYRT
char *copyright[]
=
{
"Copyright (C) "Permission is "redistribute pmot. sold for
3;
char
1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.", granted to any individual or institution to use, copy, or", this executable so long as it is not modified and that it is", profit."
*disclaimer[]
=
{ “LIKE ANYTHING ELSE THAT’S FREE, ZIP AND ITS ASSOCIATED UTILITIES ARE", “PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR", “TMPLIED. IN NO EVENT WILL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES", “RESULTING FROM THE USE OF THIS SOFTWARE." 1G #endif
/*
!NOCPYRT
*/
7,
/*
856
/
*/
/*
PGP
Source
Code
and
cme ment aloneieee s/,
/* (New File) */ /* tailor.h
-- Not copyrighted
/* Use prototypes
and ANSI
1991 Mark Adler */
libraries
if
libraries
*/
__STDC__
*/
#ifdef __STIDC__ #ifndef PROTO #define PROTO
#Hendif #define
/* !PROTO */ MODERN
#Hendif /* __STDC__ /* Use prototypes
*/ and ANSI
#if defined(sgi)
|| defined(mips)
#ifndef PROTO #define PROTO #Hendif /* !PROTO #define MODERN
*/
#Hendif /* sgi */ /* Define
#ifdef
MSDOS
__POWERC
for
Turbo
/* For
#define __TURBOC__ #endif /* __POWERC
/* Use prototypes
C as
Power
well
C too
as
Microsoft
C */
*/
+*/
and ANSI
libraries
if Microsoft
or Borland
C */
#ifdef MSDOS #ifndef PROTO #define PROTO
#Hendif
/*
!PROTO
#define
MODERN
#Hendif
/* MSDOS
*/ */
/* Turn off prototypes #ifdef NOPROTO #ifdef PROTO #undef PROTO
#endif
/* PROTO
#endif
/* NOPROT
/* Used #ifdef
if requested
*/
*/ */
to remove PROTO
#define OF(a) a Helse /* !PROTO */
arguments
in function
prototypes
for non-ANSI
C */
Internals
*/
/*
File:
#define
#endif
‘ztailor.h’
OF(a)
*/
/*
()
/* ?PROTO
*/
/* Allow far and huge allocation for small model (Microsoft /* unless NOFAR defined (needed for ANSI mode compilations) /* But
if we’re
using DJGPP,
/* zmatch routines,
and want
to use
we can’t use DYN_ALLOC.
#ifdef MSDOS #ifndef __GNUC__ #ifndef DYN_ALLOC #define DYN_ALLOC #endif #Hendif #ifdef __TURBOC__ #include #define fcalloc calloc /* Assumes #define fcfree free #else /* !__TURBOC__ */ #ifndef __GNUC__ #include #define farmalloc _fmalloc #define
farfree
#define
fcalloc(nitems,itemsize)
#define
fcfree
that
optimized
386
#ifdef
NOFAR
huge
#define far #define near #endif #else /* !MSDOS #ifdef __QNX__
#undef
huge
#undef #undef #undef #Hundef #undef
far near farmalloc farfree fcalloc
*/
#endif /* __QNX__ */ huge
#define far #define near #define farmalloc malloc #define farfree free #define fcalloc calloc #define fcfree free #endif /* ?MSDOS */ #ifdef __GNUC__ #Hifdef MSDOS /* MSDOS GNU
C ==
DJGPP
*/
C) */
assembler
+*/
But gcc has virtual memory...
arrays
are
< 64K
for
MSDOS
halloc((long) (nitems) , (itemsize) )
hfree
/* __GNUC__ */ /* ?__TURBOC__ */
#define
all
the
C or Turbo */
_ffree
#endif #Hendif #define
857
*/
*/
a
/*
858
¥*/
;
#define
huge
#define #define #define #define #define #define
far near farmalloc farfree fcalloc fcfree
PGP
malloc free calloc free
#endif
/* MSDOS
#Hendif
/* __GNUC__
*/ */
/* Define MSVMS if either #ifdef MSDOS #define MSVMS #else /* !MSDOS +*/ #ifdef VMS #define MSVMS #endif /* VMS */
#endif
/*
/* ?MSDOS
MSDOS
or
VMS
defined
*/
*/
#include #include typedef unsigned int
extent;
/* Get types and stat */ #ifdef VMS #include #include
Helse /* !VMS */ #include #include #Hendif /* 7VMS */
/* Cheap fix for unlink on VMS */ #ifdef #define
#endif
VMS unlink
delete
/* VMS */
/* For Pyramid */ #ifdef #define
#Hendif
pyr strrchr
rindex
/* pyr */
/* File operations--use #ifdef MODERN #define FOPR "rb" #define FOPM "r+b" #define FOPW "wtb"
"b"
for binary
if allowed
*/
Source
Code
and
Internals
*/
/*
File:
#else
/*
‘ztailor.h’
!MODERN
#define
FOPR
"r"'
#define
FOPM
"r+"
#define
FOPW
"wt"
#endif
*/
/*
+*/
/* ?MODERN
*/
/* Define this symbol if your target allows access to unaligned data. * This is not mandatory, just a speed optimization. The compressed * output is strictly identical.
*/ #if defined(MSDOS) defined(mc68020) #define #endif
|| defined(M_XENIX)
|| defined(vax)
|| defined(i386)
UNALIGNED_OK
/* Under MSDOS we may run * of files. Compile with * with MIN_MEM to use as
out of memory when processing a large number MEDIUM_MEM to reduce the memory requirements little memory as possible.
*/ #ifdef SMALL_MEM #define BSZ 2048 /* Buffer #else #ifdef MEDIUM_MEM #define BSZ 8192 #else
#define #endif
BSZ
16384
#endif /* end
|| \
of tailor.h
*/
size for files
*/
or
859
*/
/*
860
*/
/*
Jin wle-.2ztrees.c° /* (New File)
PGP
Source
Code
and Internals
*/
*/
/*
Copyright
(C)
1990-1992
Mark Adler,
Richard
B. Wales,
Jean-loup
Gailly,
Kai Uwe Rommel and Igor Mandrichenko. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as all of the original files are included unmodified, that it is not sold for profit, and that this copyright notice is retained.
y/ SS*
trees.c
by Jean-loup
Gailly
This is a new version of im_ctree.c for the defunct implosion method.
originally
written
by Richard
B.
Wales
PURPOSE
Encode binary
various sets code trees.
of
source
values
using
variable-length
DISCUSSION The PKZIP ''deflation" process uses several Huffman trees. The more common source values are represented by shorter bit sequences.
Each code tree is stored in the ZIP file in a compressed form which is itself a Huffman encoding of the lengths of all the code strings (in ascending order by source values). The actual code strings are reconstructed from the lengths in the UNZIP process, as described in the "application note"
(APPNOTE.TXT)
distributed
as part
of PKWARE’s
PKZIP
program.
REFERENCES Lynch, Thomas J. Data Compression: Lifetime Learning Storer,
Data
James
A.
Compression:
Computer
Techniques and Applications, pp. 53-55. Publications, 1985. ISBN 0-534-03418-7.
Science
Methods Press,
Sedgewick, R. Algorithms, p290. Addison-Wesley, 1983. HH HOR HE MH eee Hee ee ee HHHH HH HHH HK
and
1988.
ISBN
Theory, ISBN
pp.
49-50.
0-7167-8156-5.
0-201-06672-6.
*/
/*
File:
o‘ztrees.c’ > +*/
/*
861
INTERFACE
* *
(ush *attr;
ct_init
void
*
int
*method)
*
Allocate
* *
the location of the internal method (DEFLATE/STORE)
the
match
buffer,
initialize
the
various
file attribute
tables
(ascii/binary)
and
save
and
*
void
* *
ct_tally (int Save the match
dist, int lc); info and tally
the
frequency
counts.
*
long
*
flush_block
(char
ulg
*buf,
int
stored_len,
eof)
Determine the best encoding for the current block: dynamic trees, static trees or store, and output the encoded block to the zip file. Returns the total compressed length for the file so far. ‘
* * ‘*
«/ #include #include /*
"zip.h"
—————
a
a
SS
SS
SS
SSS
SS
SS
SSS
SS
SSS
* Constants
*/ #define
/* All
MAX_BITS
codes
#define
15
must
not
MAX_BL_BITS
exceed
LENGTH_CODES
/* number #define
LITERALS
/* number #define
/* end
of length
*/
exceed MAX_BL_BITS bits
*/
29
codes,
not
counting the special END_BLOCK
END_BLOCK
bytes 0..255
D_CODES
/* number
*/
code
*/
*/
256
literal
code
*/
#define L_CODES (LITERALS+1+LENGTH_CODES) /* number of Literal or Length codes, including the END_BLOCK #define
code
256
of literal
of block
bits
7
/* Bit length codes must not #define
MAX_BITS
30
of distance
codes
#define BL_CODES 19 /* number of codes used
*/
to transfer
the bit
lengths
*/
local int near extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; local
int near
extra_dbits[D_CODES]
SS
See
Se =
*/
/*
/*
862
*/
extra
;
bits
for
#410, 0;50,1
each
distance
code
/*
PGP
Source
Code
and
Internals
*/
1.2.2.3 ,3,474,5,5,6,6,%,17,8,0;020;10;20s11911, 12g te onde
local
int near extra_blbits[BL_CODES]
/* extra
bits
for
each bit
length
code
*/
=71070,0,0,0,050,0,0,0,0,050,0,0,0,2,3, 7.5
#define #define #define
STORED_BLOCK STATIC_TREES DYN_TREES
/* The three kinds
0 1 2
of block
type */
#ifndef LIT_BUFSIZE #ifdef SMALL_MEM #define LIT_BUFSIZE 0x2000 #else #ifdef MEDIUM_MEM #define LIT_BUFSIZE 0x4000 #else #define LIT_BUFSIZE 0x8000 #endif #endif #endif #define DIST_BUFSIZE LIT_BUFSIZE /* Sizes of match buffers for literals/lengths and distances. There are * 4 reasons for limiting LIT_BUFSIZE to 64K: * - frequencies can be kept in 16 bit counters - if compression is not successful for the first block, all input data is still in the window so we can still emit a stored block even when input comes from standard input. (This can also be done for all blocks if LIT_BUFSIZE is not greater than 32K.) - if compression is not successful for a file smaller than 64K, we can
even |
emit a stored
creating
new
file
Huffman
instead
trees
less
of a stored block frequently
may
not
(saving 5 bytes). provide
fast
adaptation to changes in the input data statistics. (Take for example a binary file with poorly compressible code followed by a highly compressible string table.) Smaller buffer sizes give fast adaptation but have of course the overhead of transmitting trees ka? kat Kak ham Sue ta? had Sap a? At ie Gat
=
* The
more frequently. I can’t count above current
code
is
4
general
and
allows
DIST_BUFSIZE
* memory at the expense of compression). Some * if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
< LIT_BUFSIZE
optimizations
would
+/
#define
REP_3_6
/* repeat #define
REPZ_3_10
/* repeat #define
16
previous a zero
bit length
3-6 times
(2 bits
of repeat
count)
af
length 3-10 times
REPZ_11_138
18
(3 bits
of repeat
count)
*/
*/
(to
save
be possible
*/
/*
File:
‘ztrees.c’
/* repeat /*
SSS
SSS
* Local
a zero SS
SSS
SS
+*/
length SSS
SS
/*
11-138
SS
SSS
SS
SS
times SSS
SS
(7 bits SSS
SS
SSS
SS
of repeat SS
SS
SSS
count)
2eS SSeS
SSS
*/ S555
22222======-=
;
data
*/ /* Data
structure
typedef
struct
describing
a single value
ct_data
and its code
string.
*/
{ union
{
ush freq; ush code; 3
/* frequency count /* bit string */
*/
EG
union
ol ush
dad;
/* father
ush len;
node
in Huffman
/* length of bit
tree
*/
string */
dl; ct_data;
#define
Freq fc.freq
#define #define #define
Code Dad Len
#define
HEAP_SIZE
fc.code dl.dad dl.len (2*L_CODES+1)
/* maximum heap size */ local local
ct_data near ct_data near
dyn_ltree[HEAP_SIZE]; dyn_dtree[2 * D_CODES
/* literal and length tree + 1]; /* distance tree */
*/
local ct_data near static_ltree[L_CODES + 2]; /* The static literal tree. Since the bit lengths are imposed, there is no * need for the L_CODES extra codes used during heap construction. However * The codes 286 and 287 are needed to build a canonical tree (see ct_init
* below).
*/ local
ct_data
/* The
static
near
static_dtree[D_CODES] ;
distance
tree.
(Actually
a trivial
tree
since
all
codes
* & bits~)
*/ local
ct_data
/* Huffman typedef
1) fprintf(stderr,"\ncd %3d ",(c)); send_bits(tree[c].Code, tree[c].Len); }
\
#endif
#define d_code(dist) \ ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. dist_code[256] and dist_code[257] are never * used.
*/ Hdetane MAX Gay /* the arguments /*
b)aGaee—mb acaeacneb)) must not have side
SSS
5555555555555
buffer,
*/
5555555555555
* Allocate
the
* location
of the internal file attribute
*
match
effects
initialize
the
various
tables
(ascii/binary)
(DEFLATE/STORE) .
*/
/*
Comintt */ void ct_init
(attr,
Method)
ush *attr; /* pointer to internal file attribute */ int *Method; /* pointer to compression method */ int int
n; /* iterates over tree bits; /* bit counter */
int length; int int
code; dist;
/* length value
*/
/* code value */ /* distance index
*/
file_type = attr; file_method = Method; compressed_len = input_len #ifdef
d_buf 1_buf
elements
*/
= OL;
DYN_ALLOC
= =
(ush far "(uch far
*) fcalloc (DIST_BUFSIZE, *) “feallloc*(LITABUFSIZE*/
/* Avoid using the value
if (1_buf == NULL
sizeof “2 02)e
64K on 16 bit machines
|| d_buf == NULL)
*/
(ush));
55552555
and
save
and method
the
2=>=>
*/
/*
File:
‘ztrees.c’
error
("ct_init:
*/
/*
out of memory");
#endif
if (static_dtree[0].Len != 0) return; /* ct_init already called */
/* Initialize
the mapping length
length = 0; for (code = 0;
(0..255)
< LENGTH_CODES
code
-
-> length code
(0..28)
1; codet+)
4 base_length[code]
for
length;
=
(n = 0; n < (1 = 7; /* from now on, all distances are for (; code < D_CODES; code++)
divided
{ base_dist[code] for
(n =
= dist
0; n < (1 = base) = extra[n - base]; f = tree[n] .Freq;
xbits
opt_len += (ulg) f *(bits + xbits); if (stree) static_len += (ulg) f *(stree[n].Len + xbits); Te
Covert!
owe==) 0)
return;
Trace
((stderr,
/* This happens /* Find do
the
"\nbit
length
for example
first
bit
length
overflow\n")) ;
on obj2 and pic of the Calgary which
could
increase:
corpus
*/
*/
£ bits
= max_length
while
-
1;
(bl_count[bits]
== 0)
babe
bl_count[bits]--; /* move one leaf down the tree */ bl_count[bits + 1] += 2; /* move one overflow item as
its
brother
bl_count [max_length]--; /* The
brother
* but this
of the
does not
*/ overflow
while
-=
(overflow
2;
> 0);
overflow
affect
item
also
moves
bl_count [max_length]
one
step up,
*/
871
*/
/*
872
*/
/*
/* Now recompute
* h is still * lengths
* from
all bit
lengths,
scanning
equal to HEAP_SIZE.
instead
’ar’
of fixing
Source
in increasing
Code
wrong
ones.
This
and
Internals
frequency.
(It is simpler to reconstruct
only the
written by Haruhiko
PGP
idea
all
is taken
Okumura.)
*/ for
(bits
= max_length;
bits
!= 0; bits--)
n = bl_count [bits]; mnsihe Ga Y=
m = heap[--h]; if
(m > max_code) continue;
if (tree[m].Len Trace
!= (unsigned)
((stderr,
opt_len
+=
"code
((long)
tree[m].Len
bits)
%d bits
bits
%d->%d\n",
- (long)
m,
tree[m].Len,
tree[m].Len)
* (long)
bits));
tree[m] .Freq;
= bits;
}
Tinos
}
t
} /*
=
SSS
5555555555525
* Generate
the
codes
for
5255555555
5555555552555
a given tree
and bit
5555555555555
counts
5555555555555
(which need not
be
* optimal). * IN assertion: the array bl_count contains the bit length statistics * the given tree and the field len is set for all tree elements. * OUT assertion: the field code is set for all tree elements of non ce zero code length.
for
+/ /*
gen_codes +/ local
void
gen_codes
(tree,
ct_data int
near
max_code;
max_code) *tree;
/* the
/* largest
ush next_code[MAX_BITS
tree
code
+ 1];
to
with
/* next
ush code = 0; /* running code value
decorate
*/
non
frequency
code
zero
value
for
each
*/
bit
length
*/
*/
int bits; /* bit index */ int n; /* code index */ /* The distribution counts * without bit reversal.
are
first
used
#7,
for
(bits
=
1; bits)
E>=>=>=
*/
/*
File:
‘ztrees.c’
*/
/*
873
sl next_code[bits]
=
code
/* Check that the bit * must be all ones.
=
(code
counts
+ bl_count[bits
in bl_count
are
-
1])
consistent.
= = 1 && blcodes >= 4, "not enough codes"); L_CODES && dcodes > 3; static_lenb
and get the
Yu ",
*/
/*
File:
‘ztrees.c’
+*/
#ifdef FORCE_METHOD if (level == 1 && eof
{ /* force
&&
/*
compressed_len
stored file
==
OL)
*/.
#else
if (stored_len
= 0x2000
13 /* used in unShrink() +*/ (1 ¢ aneo eco ee a REBZE DELS 8 repaean sup eseks ans suldaroe wisi eae: RE BZ23 210 reer ety irs ou eee me ka ete
239 718 (Alf) 707 891 243 586 862 862 862
Eescale(r,currentp,newp)
570
aa...
eneaber
PRESTU) Se opened eoaeMt Geka citebeLausdels fentonlon etsous yeee(easyo,sheasye 888 REW DA iernaeaaeieubaraketde 2acaalouuada cae. aac etek 855
TEVerse at bTiG) cs Meyers, 6 syels, minis p hee tae
546
RE VALS LON erresenep-conatevsteusayoters( 0)alae Sereaie silane teisls areas FO TU pegepepienst-a5y-cdtpaite tcc neti «ice "vovartenahs otsiresovar'ev/econe.enauaans HARA: GOR DHM=s Yel Exertekenettte tenetoletaetetereteioistctahet cheat RSASDECRZERRORG sa 00 «cere dere cielsiatete srateleyevs ater selela RSACENCREERROR wuts crereae l ore «1-12,